JDK에는 Java에서 편집 프로세스를 시작할 수있는 관련 컴파일 API가 있습니다. Java 소스 파일을 구문 분석하고 구문 트리를 얻습니다. 이 완전한 API 세트는 JDK의 도구에 포함되어 있습니다 (/library/java/java/javavirtualmachines/jdk_version/contents/home/lib에서 찾을 수 있습니다). 그러나 이것은 Oracle 및 OpenJDK 릴리스의 공개 API가 아니므 로이 API 세트를 설명 할 공식 문서는 없습니다. 그러나 많은 프로젝트 에서이 API를 사용하여 많은 일을했습니다. 예를 들어, 유명한 Lombok 은이 API를 사용하여 주석 처리 단계에서 소스 코드에서 구문 트리를 수정했습니다. 최종 결과는 새 코드를 소스 파일에 직접 삽입하는 것과 같습니다!
이 API 세트에는 현재 관련 문서가 부족하기 때문에 사용하기가 어렵습니다. 예를 들어 소스 코드의 모든 변수를 구문 분석하고 인쇄합니다.
공개 클래스 javaparser {private static final String path = "user.java"; Private JavacfileManager filemanager; 개인 Javactool Javactool; public javaparser () {context context = new Context (); filemanager = new JavacFileManager (컨텍스트, true, charset.defaultcharset ()); javactool = 새로운 javactool (); } public void parsejavafiles () {iterable <!-? javafileobject-> files = filemanager.getjavafileobjects (Path); javacompiler.compilationtask compilationtask = javactool.gettask (null, filemanager, null, null, null, 파일); javactask javactask = (Javactask) compilationtask; {iterable <!-? CompilationUnittree를 확장합니다-> result = javactask.parse (); for (compilationUnittree tree : result) {tree.accrect (new SourceVisitor (), null); }} catch (ioexception e) {e.printstacktrace (); }} 정적 클래스 소스 Visitor 확장 Treescanner <void, void = ""> {private String currentpackagename = null; @override public void vosit compilationUnit (compilationUnittree 노드, void 피피) {return super.visitCompilationUnit (노드, 피하기); } @Override public void visitVariable (variabletree node, void reving) {formatptrln ( "variable name : %s, type : type : %s, 종류 : %s : %s", node.getname (), node.gettype (), node.getKind (), currentPackAgename); 널 리턴; }} public static void formatptrln (문자열 형식, 객체 ... args) {system.out.println (string.format (format, args)); } public static void main (String [] args) {new javaparser (). parsejavafiles (); }} </void,>user.java 코드는 다음과 같습니다.
패키지 com.ragnarok.javaparser; import com.sun.istack.internal.nullable; import java.lang.override; 공개 클래스 사용자 {@Nullable Private String foo = "123123"; 개인 foo a; public void usermethod () {} 정적 클래스 foo {private String foostring = "123123"; public void foomethod () {}}}위의 Javaparser를 실행 한 결과는 다음과 같습니다.
변수 : foo, Annotaion : nullablevariable 이름 : foo, 유형 : 문자열, 종류 : 변수, 패키지 : com.ragnarok.javaparserver 변수 이름 : a, type : foo, since : 변수 : com.ragnarok.javaparser
여기서 먼저 javacompiler.compilationtask를 통해 소스 파일을 구문 분석 한 다음 Custom SourceVisitor (Treescanner에서 상속)를 사용하여 소스 코드의 구조에 액세스하십시오. SourceVisitor 클래스에서는 컴파일 장치 (단일 소스 코드 파일)를 구문 분석하고 모든 변수에 액세스하기 위해 VisitVariable을 과부하합니다. 여기서는이 변수 유형 (패키지 이름 포함)의 자격을 갖춘 이름을 얻을 수 없으며 해당 간단한 이름 만 얻을 수 있음을 알 수 있습니다. 따라서 유형을 결정하려면 자체적으로 결정하기 위해 외부 구현이 필요합니다. 예를 들어, 클래스가 위치한 패키지 이름을 녹음하고 전체 소스 코드 디렉토리를 재귀 적으로 검색하여 모든 클래스의 완전히 자격있는 이름을 추적하고 가져 오기에 해당 유형이 포함되어 있는지 여부를 찾을 수 있습니다.
Treescanner는 VisitVariable 방법 외에도 다수의 다른 visitxyz 방법을 포함합니다. 예를 들어, 모든 가져 오기, 메소드 정의, 주석 등을 통과 할 수 있습니다.보다 구체적으로 보려면 OpenJDK에서 이에 대한 소스 코드를 볼 수 있습니다.
여기서 우리는 다른 예를 들어 모든 내부 클래스와 클래스 자체에 액세스하기 위해 VisitClass 메소드를 과부하시킵니다.
@OverRidePublic void visitClass (classtree node, void fea) {formatptrln ( "클래스 이름 : %s", node.getSimplename ()); for (tree memb List <!-? annotationTree-> annotations = variable.getModifiers (). getAnnotations (); if (annotations.size ()> 0) {formatptrln ( "variable : %s, annotaion : %s", variable.getname (), annotations.get (0) .getAnnotationType ()); } else {formatptrln ( "변수 : %s", variable.getName ()); }}} return super.visitClass (노드, 피하기); }여기서는 클래스 이름과 변수 이름, 유형 및 주석 유형을 인쇄합니다. 위의 코드를 실행하면 결과는 다음과 같습니다.
클래스 이름 : uservariable : foo, Annotaion : nullablevariable : 클래스 이름 : foovariable : foostring
클래스 이름과 클래스의 변수를 인쇄했음을 알 수 있습니다. VisitClass 메소드에서는 다른 유형에 해당하는 변수, 메소드, 주석 등을 포함하여 GetMembers 메소드를 통해 클래스의 모든 구성원을 얻을 수 있습니다. 예를 들어, 변수는 variabletree 유형에 해당하고 메소드는 MethodTree 유형에 해당합니다.
일반적으로 사용은 실제로는 특히 복잡하지는 않지만 문서화 부족으로 인해 큰 장애물을 사용하게되었습니다. 그리고 우리가 소개하는 것은이 API의 작은 부분 일뿐입니다. 앞으로이 API의 관련 기능을 계속 연구 할 것입니다.
위는 Java 소스 코드를 구문 분석하기 위해 JDK의 파서 데이터를 편집 한 것입니다. 우리는 향후 관련 정보를 계속 추가 할 것입니다. 이 사이트를 지원 해주셔서 감사합니다!