2010-01-07 2 views
7

일부 Java 코드를 처리하는 데 일식 JDT AST 파서를 사용 중이며 필드 및 메서드 선언의 형식 바인딩을 추출하려고합니다. 그 일을하기위한 논리는 내 Visitor 클래스 안에 있습니다 (아래 참조). 불행히도, 나는 운이 없으며 바인딩 중 아무 것도 해결되지 않습니다 (그들은 항상 null입니다). 흥미로운 점은 바인딩이 Eclipse ASTView 플러그인과 동일한 코드에서 작동한다는 것입니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?바인딩이 식의 AST 처리로 해결되지 않습니다.

다음은 상황을 파악하는 데 도움이되는 관련 코드 조각입니다.

ASTParser parser = ASTParser.newParser(AST.JLS3); 
parser.setKind(ASTParser.K_COMPILATION_UNIT); 
parser.setSource(source); 
parser.setResolveBindings(true); 
CompilationUnit unit = (CompilationUnit) parser.createAST(null); 

GenericVisitor visitor = new GenericVisitor(outDir + "//" + file.getName() + ".xml"); 
visitor.process(unit); 


public class GenericVisitor extends ASTVisitor 
{ 
    public void endVisit(FieldDeclaration node) 
    { 
     String bindingInfo = "";  
     ITypeBinding binding = node.getType().resolveBinding(); 

     if(binding == null) 
     {      
     System.out.println("field declaration binding = null"); 
     } 
     else 
     { 
     bindingInfo = binding.getQualifiedName(); 
     } 

     endVisitNode(node, bindingInfo); 
    } 

    public void endVisit(MethodInvocation node) 
    { 
     String bindingInfo = ""; 
     IMethodBinding binding = node.resolveMethodBinding(); 

    if(binding == null) 
    {      
     System.out.println("method binding = null"); 
    } 
    else 
    { 
     bindingInfo = binding.toString(); 
    } 

    endVisitNode(node, bindingInfo); 
    } 
} 

답변

2

아마도 Visitor 인스턴스에서 메서드를 호출하면 안됩니다.

unit.accept(visitor); 

CompilationUnit, ASTNode의 부모 클래스가 입력 ASTVisitor이다 방문자를 취하는 accept 방법이있다 : 당신은 뭔가를해야한다. 당신이 쓴

방문자, GenericVisitor는, 서브 클래스에게 abstarct에서 클래스 ASTVisitor을 수행하고 당신이 둘다 노드 유형에 대한 구현을 재정의합니다. 그래서 해결하는 것입니다 위의 형태로 호출을 수행하는 코드를 변경하는 생각하여 문제.

1

ASTParser는 컴파일러의 첫 번째 단계 인 AST를 작성합니다. 실제 컴파일러는 그 이상을 수행합니다. 추가 정보로 트리를 향상시키는 다양한 방문자를 실행합니다. 그 중 하나는 바인딩 해결 방문자입니다.

특히 org.eclipse.jdt.internal.compiler.Compiler 클래스의 public void process (CompilationUnitDeclaration unit, int i) 메서드의 본문을 살펴보십시오.

0

바인딩이 null 인 경우, 다른 설명에 문제가 있음을 확신하지 못합니다. 우리의 코드베이스에서, 우리는 다음을 수행하고, 바인딩은 항상있다 :

public static ASTNode getASTNodeFromCompilationUnit(ICompilationUnit compUnit) { 
    ASTParser parser = ASTParser.newParser(AST.JLS3); 
    parser.setResolveBindings(true); 
    parser.setSource(compUnit); 
    return parser.createAST(/* passing in monitor messes up previous monitor state */ null); 
} 

그래서 내가 볼 수있는 유일한 차이는 바인딩을 해결하기 위해 호출의 순서, 우리는 전화를하지 않는 것이 사실이다 파서에 setKind. 이 코드로 정확히 시도해보고 어떤 일이 벌어지는 지 볼 수있는 기회?

8

사용할 때 : parser.setSource (source); "source"매개 변수의 유형은 무엇입니까?

바인딩 정보는 Java 모델에서 가져옵니다. 즉, 컴파일 단위는 Java 모델에 상대적인 이어야합니다. 이 코드는 소스 코드가 setSource (ICompilationUnit) 또는 setSource (IClassFile)에서 오는 경우 자동으로 발생합니다. setSource (char [])로 소스가 인 경우 setProject (IJavaProject) 및 setUnitName (String)을 호출하여 위치를 명시 적으로 위치에 지정해야합니다.

http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html 에서입니다

내가 방금 setProject (IJavaProject)와 setUnitName (String)를 호출하지 않고 setSource (문자 [])를 사용 어쩌면 생각

+0

한도 parser.setEnvironment (...)를 사용할 수 있습니다. "더 IJavaProject를 사용할 수 없을 때 사용할 수있는 환경 설정" – roesslerj

-1

때때로, 당신이 참조 된 소스 파일의 오류를 가지고있는 경우, 이러한 유형에 대한 바인딩은 해결되지 않습니다. 예를 들어 올바른 인코딩과 Java 버전의 소스를 사용해야합니다.

ASTParser parser = ASTParser.newParser(AST.JLS3); 
    parser.setKind(ASTParser.K_COMPILATION_UNIT); 
    parser.setResolveBindings(true); 
    parser.setBindingsRecovery(true); 
    Hashtable<String, String> options = JavaCore.getDefaultOptions(); 
    options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6); 
    parser.setCompilerOptions(options); 
    parser.setEnvironment(classpath, sources, new String[] { "UTF-8", "UTF-8" }, true); 
    parser.setSource(fileContents.toCharArray()); 
    CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null); 
    IProblem[] problems = compilationUnit.getProblems(); 
    if (problems != null && problems.length > 0) { 
     logger.warn("Got {} problems compiling the source file: ", problems.length); 
     for (IProblem problem : problems) { 
      logger.warn("{}", problem); 
     } 
    } 
    return compilationUnit; 
+0

나는 이것과 비슷한 것을 구현하려고하는데, classpath와 sources 변수는 무엇인가? 그들의 가치관을 보여줄 수 있습니까? – Braden

+0

클래스 경로 및 소스는 java -classpath 옵션에서 제공하는 것처럼 실제 경로가있는 문자열 배열입니다. 죄송합니다. 응답하는데 너무 오래 걸렸습니다 ... – roesslerj

1

좋아요, 이것은 스택 오버플로에 대한 첫 번째 답변입니다. 신경 ...

나는 당신과 같은 문제를 가지고, 그리고 작업이 완료 이후이 :

parser.setResolveBindings(true); 

는의가이 확인하여 작동 여부를 확인하자

if (unit.getAST().hasResolvedBindings()) { 
    System.out.println("Binding activated."); 
} 
else { 
    Ststem.out.println("Binding is not activated."); 
} 

을 그리고 내가 생각 결과는 "바인딩이 활성화되지 않았습니다."입니다. 그래서 당신은 널 포인터를 항상 가지고 있습니다.

그럼, 내 코드에이 문을 추가 :

parser.setEnvironment(null, null, null, true); 

마술이 문제가 해결! 그리고 당신도 이것을 시도 할 수 있다고 생각합니다.

+0

setEnvironment는 JDT 3.6 이상에서만 사용할 수 있지만 Maven은 최대 3.3 개까지 사용할 수 있습니까? 3.6을 어떻게 설치 했습니까? –

1

문제는 바인딩 분석에 필요한 Java 모델을 구성하는 데 필요한 정보가 파서에 제공되지 않았기 때문입니다.

파서의 소스가 setSource(ICompilationUnit) 또는 setSource(IClassFile)에서 얻으면이 정보는 파서에 자동으로 제공됩니다.

그러나 setSource(char[])을 대신 사용하는 경우 파서에이 컨텍스트를 제공해야합니다. 이 중 하나가 parser.setProject(IJavaProject) 또는 setEnvironment(String[], String[], String[], boolean)setUnitName(String)

를 호출하여 수행 할 수 있습니다 출처 : http://help.eclipse.org/kepler/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html#setResolveBindings(boolean)

관련 문제