2012-12-03 4 views
17

annotation processor을 작성하여 클래스에 메소드 및 필드를 삽입하려고합니다 ... 문서가 너무 희박합니다. 나는 멀지는 않을 것이고 내가 올바르게 접근하는지 모르겠습니다.주석 처리기로 코드 교체

처리 환경은 Filer 개체를 제공합니다.이 개체에는 새로운 원본 및 클래스 파일을 만드는 편리한 방법이 있습니다. 그런 다음 잘 작동하지만 기존 소스 파일을 읽는 방법을 알아 내려고했습니다.이 파일은 모두 "getResource"입니다. 그래서 내 프로세서 구현에 나는이 짓을했는지 :

@Override 
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
    try { 
     for (TypeElement te : annotations) { 
      for (Element element : roundEnv.getElementsAnnotatedWith(te)) { 
       FileObject in_file = processingEnv.getFiler().getResource(
        StandardLocation.SOURCE_PATH, "", 
        element.asType().toString().replace(".", "/") + ".java"); 

       FileObject out_file = processingEnv.getFiler().getResource(
        StandardLocation.SOURCE_OUTPUT, "", 
        element.asType().toString().replace(".", "/") + ".java"); 

       //if (out_file.getLastModified() >= in_file.getLastModified()) continue; 

       CharSequence data = in_file.getCharContent(false); 

       data = transform(data); // run the macro processor 

       JavaFileObject out_file2 = processingEnv.getFiler().createSourceFile(
        element.asType().toString(), element); 
       Writer w = out_file2.openWriter(); 
       w.append(data); 
       w.close(); 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
     processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); 
    } 
    return true; 
} 

내 첫 당황 내가 아닌 element.asType().toString().replace(".", "/") + ".java"이 (정규화 된 형식 이름을 얻고 패키지 및 소스 파일 경로로 변환) 느낌 도움이되지 수있다 문제에 접근하는 좋은 방법. 나머지 API는 너무 지나치게 조작되었지만 원래 소스 코드를 검색하는 편리한 방법은없는 것처럼 보입니다.

실제 문제는 컴파일러가 출력 디렉토리의 두 번째 소스 파일 ("오류 : 중복 클래스")에 의해 자발적으로 화가 나서 이제 막혔다는 것입니다.

필자는 나머지 부분을 이미 작성했습니다 - 일부 데이터를 계산하고 필드 값과 메소드를 삽입하기위한 매크로 렉서 (macro lexer)와 파서 (parser) 등은 컴파일러 외부의 초기 단계로 작동합니다. 원본 파일이 .java 확장자를 가질 수 없다는 점을 제외하면 (컴파일러가 파일을 보지 못하게하기 위해) 이것은 잘 작동합니다. 그런 다음 주석이 코드 생성을 수행 할 수 있다고 들었습니다. 코드 생성은 더 정확하고 편리 할 것이라고 생각하지만 많은 지침을 찾을 수는 없습니다.

+1

참조 : http://techbitsfromsridhar.blogspot.ca/2013/02/java-compiler-plug-ins-in-java-8-use.html –

답변

16

주석 프로세서 뒤에있는 의도는 개발자가 기존 클래스를 대체하지 않고 새 클래스를 추가 할 수 있도록하기위한 것입니다. 즉, 기존 클래스에 코드를 추가 할 수있는 버그가 있습니다. Project Lombok에는 leveraged이 있습니다.이 클래스는 getter 및 setter (다른 것들 중에서도)를 컴파일 된 Java 클래스에 추가합니다.

메소드/필드를 '대체'하는 방법은 입력 클래스에서 확장되거나 입력 클래스에 위임됩니다. 이를 통해 호출을 대상 클래스로 재정의/전환 할 수 있습니다.

그래서 당신의 입력 클래스 인 경우

InputImpl.java :

InputReplacementImpl.java :

public class InputReplacementImpl implmements Input{ 

    private Input delegate; 

    //setup delegate.... 

    public void foo(){ 
     System.out.println("foo replacement"); 
    } 
    public void bar(){ 
     delegate.bar(); 
    } 
} 

public class InputImpl implmements Input{ 
    public void foo(){ 
     System.out.println("foo"); 
    } 
    public void bar(){ 
     System.out.println("bar"); 
    } 
} 

당신은 그것을 "대체"다음을 생성 할 수

이것은 질문을 구걸합니다. InputReplacementImpl을 어떻게 참조합니까? 티파니는 InputImpl입니다. 래핑을 수행하는 코드를 더 생성하거나 단순히 생성 될 것으로 예상되는 코드의 생성자를 호출 할 수 있습니다.

귀하의 질문이 무엇인지 잘 모르겠지만이 문제가 귀하의 문제를 밝히기를 바랍니다.

+0

* Ah ha! * 이전에 롬복을 본 것으로 생각합니다. 부분적으로 이것이 불가능하다고 생각할 이유가 없었습니다. 이 대답은 컴파일러 오류를 설명하고 나에게 몇 가지 선택을 제공합니다. 나는 AST 해킹에 빠져들고 싶지 않다. 현재, 간단한 regexps가 나를 찾아 코드를 교체 할 때. 원래 클래스가 완전하고 컴파일 가능하지 않기 때문에 클래스에 위임하는 것이 실제로 가능하지 않습니다.지금까지 보았 듯이 주석 API에 대한이 어리석은 제한은 복잡성에도 불구하고 유용하지 않다는 것을 의미합니다. 하지만 이제는 무엇을해야할지 알았습니다. 특수 효과를 사용하지 마십시오! 당신의 도움을 주셔서 대단히 감사합니다. – Boann

+0

확실한 것 @ 보얀, 프로젝트에 행운을 빈다. –