2010-01-07 4 views
7

Estoy usando el analizador eclipse JDT AST para procesar algunos códigos Java y estoy tratando de extraer los enlaces de tipo para los campos y las declaraciones de métodos. La lógica para hacer eso está dentro de mi clase de visitante (ver a continuación). Desafortunadamente, no estoy teniendo suerte y ninguno de los enlaces se está resolviendo (son consistentemente nulos). Lo interesante es que las vinculaciones sí funcionan en el mismo código con el complemento eclipse ASTView. ¿Qué estoy haciendo mal?enlaces que no se resuelven con el procesamiento AST en eclipse

Aquí hay algunos fragmentos de código relevantes que esperamos ayuden a alguien a descubrir qué está pasando.

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); 
    } 
} 

Respuesta

2

La razón probable es que no se debe llamar directamente al método en la instancia de visitante. Usted debe hacer algo como:

unit.accept(visitor); 

La clase padre de CompilationUnit, ASTNode, tiene un método accept que tiene un visitante que es de tipo ASTVisitor.

El visitante que ha escrito, GenericVisitor, hace subclases de la clase abstarct ASTVisitor y prevalece sobre la aplicación de los tipos de nodo que está en trayectos al. Así que creo que cambiar su código para hacer la invocación en forma anterior sería arreglar su problema.

1

ASTParser es solo el analizador sintáctico: construye un AST que es el primer paso en la compilación. El compilador real está haciendo más que eso: ejecuta varios visitantes que mejoran el árbol con información adicional. Uno de ellos es el visitante de resolución vinculante.

En particular, eche un vistazo al cuerpo del proceso de vacío público (CompilationUnitDeclaration unit, int i) en la clase org.eclipse.jdt.internal.compiler.Compiler.

0

Si sus enlaces son nulos, no estoy del todo seguro de que su problema esté cubierto por las otras explicaciones. En nuestra base de código, hacemos lo siguiente, y los enlaces son siempre allí:

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); 
} 

Así que las únicas diferencias que puedo ver son del orden de las llamadas para resolver las fijaciones y el hecho de que no llamamos setKind en el analizador. ¿Alguna posibilidad de probarlo con exactamente este código y ver qué pasa?

8

Cuando usa: parser.setSource (fuente); ¿Cuál es el tipo de param "fuente"?

La información de enlace se obtiene de el modelo de Java. Esto significa que la unidad de compilación debe estar ubicada en en relación con el modelo de Java. Este se produce automáticamente cuando el código fuente proviene de setSource (ICompilationUnit) o ​​ setSource (IClassFile). Cuando la fuente es suministrada por setSource (char []), la ubicación debe establecerse explícitamente llamando al setProject (IJavaProject) y setUnitName (String).

Esto es de http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html Creo que tal vez sólo tiene que utilizar setSource (char []) sin llamar setproject (IJavaProject) y setUnitName (String)

+0

También se puede utilizar parser.setEnvironment (...): "Establecer el medio ambiente que se puede utilizar cuando no hay IJavaProject están disponibles" – roesslerj

-1

A veces, si tienes errores en los archivos de origen que se hace referencia, entonces las consolidaciones a estos tipos no se resuelven. Por ejemplo, asegúrese de usar la codificación correcta y la versión de Java de la fuente.

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

Estoy tratando de implementar algo similar a esto, ¿cuáles son las variables classpath y fuentes aquí? ¿Puedes dar un ejemplo de sus valores? – Braden

+0

classpath y sources son matrices de Strings con rutas reales como las que se les daría en la opción java-classpath. Lo siento, me tomó tanto tiempo responder ... – roesslerj

1

Bien, esta es mi primera respuesta en Stack Overflow. Nervioso ...

que tiene el mismo problema con usted, y puesto que usted ha hecho esto:

parser.setResolveBindings(true); 

Vamos a ver si funcionaba marcando esta:

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

y creo que la el resultado es "La vinculación no está activada". Y es por eso que tienes el puntero nulo todo el tiempo.

Entonces, añado esta declaración a mi código:

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

Por arte de magia, se solucione el problema !!! Y supongo que puedes probar esto también.

+0

parece que setEnvironment solo está disponible desde JDT 3.6 en adelante, pero Maven solo tiene hasta 3.3? ¿Cómo instalaste 3.6? –

1

El problema es que a su analizador no se le ha proporcionado la información necesaria para construir su Modelo Java que se requiere para resolver enlaces.

Si la fuente del analizador se obtiene desde setSource(ICompilationUnit) o setSource(IClassFile) esta información se proporciona automáticamente al analizador.

Sin embargo, si usa setSource(char[]), debe proporcionar este contexto para el analizador. Esto se puede hacer ya sea llamando o parser.setProject(IJavaProject)setEnvironment(String[], String[], String[], boolean) y setUnitName(String)

Fuente: http://help.eclipse.org/kepler/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html#setResolveBindings(boolean)

Cuestiones relacionadas