2012-01-17 3 views
10

Eclipse의 JDT 컴파일러는 계단식 컴파일을 수행 할 수있는 findType(...) 메서드를 정의하는 INameEnvironment 인터페이스를 제공합니다. 흥미롭게도 표준 JDK 컴파일러 툴킷을 사용하여이를 수행 할 수있는 방법이 있는지 알고 싶습니다.javax.tool을 사용한 계단식 메모리 컴파일

이 시나리오가 간 종속성이 템플릿 파일 생성 된 클래스에 대한 메모리 편집에서 할 템플릿 엔진이며, 그것은 당신이 템플릿 파일을 발생 순서를 예상 할 수없는, 따라서 Foo 세력이 먼저 컴파일 될 필요가 부모 Bar가 이미 컴파일되기 전에 그러므로 당신은 당신이 Foo의 편집을 계속하는 다른 소스 Bar를 생성하려면 먼저 컴파일해야 Foo의 컴파일시 의미 캐스케이드 컴파일을 할 수있는 메커니즘이 필요합니다 : 등 일부 코드는 다음과 같습니다

private NameEnvironmentAnswer findType(final String name) { 
    try { 
     if (!name.contains(TemplateClass.CN_SUFFIX)) { 
      return findStandType(name); 
     } 

     char[] fileName = name.toCharArray(); 
     TemplateClass templateClass = classCache.getByClassName(name); 

     // TemplateClass exists 
     if (templateClass != null) { 

      if (templateClass.javaByteCode != null) { 
       ClassFileReader classFileReader = new ClassFileReader(templateClass.javaByteCode, fileName, true); 
       return new NameEnvironmentAnswer(classFileReader, null); 
      } 
      // Cascade compilation 
      ICompilationUnit compilationUnit = new CompilationUnit(name); 
      return new NameEnvironmentAnswer(compilationUnit, null); 
     } 

     // So it's a standard class 
     return findStandType(name); 
    } catch (ClassFormatException e) { 
     // Something very very bad 
     throw new RuntimeException(e); 
    } 
} 

답변

2

우리의 코멘트 대화를 바탕으로, 나는 그 대답이 분명하다고 생각한다 : 아니오, 당신은 JDK 컴파일러로 그렇게 할 수 없다. 특정 클래스 종속성이 아니라 패키지를 요청할 때 훅을 제공합니다. 내가 아는 한 지금까지 얻을 수있는 가까운 약

은 다음과 같습니다 코드

Here's a nice article는 메모리 클래스에서 처리하도록 할 필요가 있지만. 특히 설명하는 문제는 JavaFileManager.list(...) 방법으로 처리됩니다. 여기서 JavaFileObjects를 메모리에 캐시해야합니다. 기사에 설명 된대로 ForwardingJavaFileManager의 하위 클래스를 만들어야 할 가능성이 높습니다. 작업중인 캐시 된 클래스를 처리하도록 수정되었지만.

뭔가를 컴파일하는 데 사용할 수 있습니다. 오류가 반환되면 regex를 사용하여 누락 된 항목을 찾으십시오. 누락 된 코드를 생성/컴파일 한 후 원래 코드를 다시 컴파일하십시오.

참고 : ForwardingFileManager.list (...)에서 종속 클래스의 FQN을 어느 시점에서 packageName 인수로 요청합니다. 나는 그 시점에서 반을 반납하려하지 않았다. 패키지가 불일치하기 때문에 작동하지 않을 수도 있지만 어쩌면 그렇게 될 수도 있습니다.

+0

JDT의'INameEnvironment.findType()'의 요점은 계단식 컴파일을 할 수 있다는 것입니다. 클래스'Bar'에 의존하는'Foo' 클래스가 있습니다. 그리고 내 응용 프로그램은'Foo'를 컴파일하기 전에'Foo'를 컴파일하려고합니다. 따라서'Foo'의 컴파일 과정에서'Bar'의 소스 코드를 생성하고 컴파일 한 후'Foo' 컴파일을 계속하는 로직을 구현할 수 있습니다. 이런 종류의 물건은'ForwardJavaFileManager'로 할 수 있습니까? –

+0

당신이 설명하는 것의 꼭대기에 그런 종류의 것을 구현할 수있을 것입니다. 나는 비슷한 것을합니다. 특정 오류가 발생하면 regex를 사용하여 누락 된 부분을 찾아 스텁을 생성/컴파일합니다. 그러나 JDT가 누락 된 기호를 찾기 위해 컴파일 중간에 바로 갈고리를 제공한다고 말하면 Javac이 사용할 수 있다고 생각하지 않습니다. 당신은 미리, 또는 오류, 또는'list (...와 함께 그것을 알아 내야한다.)'호출은 패키지를위한 것이므로, 특정 패키지에 대한 요청이 당신이 무언가를 생성해야 함을 의미한다는 것을 안다면, 그곳에서 캐스케이드를 컴파일 할 수있다. – mentics

+0

흠 ... 아마도 내가가는 길은 아닙니다. 요점은 B를 컴파일 할 때, A가 누락 된 것을 발견했지만, 클래스 A가 누락되지 않았을뿐 아니라 소스 코드도 준비되지 않았기 때문에, 템플릿 파일 [a]에서 소스 코드 A를 생성해야합니다. JDT의'findType' 호출은 필요에 완벽하게 맞습니다. –

1

예제를 통해이 HelloWorld 예제를 읽으면 문제가 해결되는지 확인하십시오. 코드를 게시하지 않으면 특정 문제가 무엇인지 말할 수 없습니다.

+0

여기에 해당합니다. 컴파일 할 소스 코드가 2 개 있다고 가정 해 보겠습니다. 하나는 "package foo; public class One {...}"이고 다른 하나는 "package bar; import foo.One; public class Two {...}"입니다. 두 번째 클래스 인 "Two"를 컴파일하기 전까지는 모든 것이 괜찮습니다. 컴파일러는 foo.One을 찾을 수 없다고보고합니다. 알았어. –

+0

. 나는 이것을 남겨두고보다 나은 해결책을 모색 할 것이다. URL 클래스 로더가 필요한 것 같습니다. –

+0

그래서 표준 태양열 JDT 컴파일러를 포기하고 ECJ로 끝납니다. 새로운 결과가 있습니까? –

관련 문제