2009-06-10 4 views
4

den folgenden Code in Eclipse Gegeben:Eclipse-Abstract Syntax-Baum Diff

import org.eclipse.jdt.core.dom.AST; 
import org.eclipse.jdt.core.dom.ASTParser; 
import org.eclipse.jdt.core.dom.CompilationUnit; 

public class Question { 
    public static void main(String[] args) { 
     String source = "class Bob {}"; 
     ASTParser parser = ASTParser.newParser(AST.JLS3); 
     parser.setSource(source.toCharArray()); 
     CompilationUnit result = (CompilationUnit) parser.createAST(null); 

     String source2 = "class Bob {public void MyMethod(){}}"; 
     ASTParser parser2 = ASTParser.newParser(AST.JLS3); 
     parser2.setSource(source2.toCharArray()); 
     CompilationUnit result2 = (CompilationUnit) parser2.createAST(null); 
    } 
} 

Wie verwenden Sie das Eclipse Vergleichen API (org.eclipse.compare) die AST Differenz zu finden? (Und kann dies außerhalb eines Plugins getan werden?)

Ich

http://kickjava.com/src/org/eclipse/compare/structuremergeviewer/Differencer.java.htm http://kickjava.com/src/org/eclipse/jdt/internal/ui/compare/JavaStructureCreator.java.htm http://kickjava.com/src/org/eclipse/compare/CompareUI.java.htm

Kann mir jemand Punkt zu Beispielcode in den folgenden APIs suchen (oder eine API - aber die Code ist bevorzugt).

Antwort

2

Vorausgesetzt, dass Eclipse AST nicht differenziert, vielleicht wollte das OP Unterschiede zwischen zwei Dateien in Bezug auf die Sprachkonstrukte finden, die Leerräume und Kommentare ignorieren. Unser Smart Differencer tool vergleicht zwei Quelldateien in Bezug auf die Sprachkonstrukte (Variablen, Ausdrücke, Anweisungen, Blöcke, Methoden, ...) und beschreibt die Unterschiede im Hinblick auf abstrakte Editieroperationen über diese Elemente (Löschen, Kopieren, Verschieben, Benennen umbenennen in Region, ...)

+0

Gibt es Open Source-Lösungen? –

+0

Apparantly nicht http://stackoverflow.com/questions/3829453/is-there-any-free-ast-diff-tool –

5

GumTree macht den Job, kostenlos :)

Es sind auch andere Sprachen wie JavaScript unterstützt.

1

Tatsächlich ist die Überprüfung auf Gleichheit einfach, mit den Eigenschaften eines ASTNode. Danach liegt es an Ihnen, wie Sie die Unterschiede erreichen wollen. Überprüfen Sie das Codebeispiel auf Gleichheitsprüfung:

public class ASTCompare { 

    @SuppressWarnings("unchecked") 
    static boolean equals(ASTNode left, ASTNode right) { 
     // if both are null, they are equal, but if only one, they aren't 
     if (left == null && right == null) { 
      return true; 
     } else if (left == null || right == null) { 
      return false; 
     } 
     // if node types are the same we can assume that they will have the same 
     // properties 
     if (left.getNodeType() != right.getNodeType()) { 
      return false; 
     } 
     List<StructuralPropertyDescriptor> props = left 
       .structuralPropertiesForType(); 
     for (StructuralPropertyDescriptor property : props) { 
      Object leftVal = left.getStructuralProperty(property); 
      Object rightVal = right.getStructuralProperty(property); 
      if (property.isSimpleProperty()) { 
       // check for simple properties (primitive types, Strings, ...) 
       // with normal equality 
       if (!leftVal.equals(rightVal)) { 
        return false; 
       } 
      } else if (property.isChildProperty()) { 
       // recursively call this function on child nodes 
       if (!equals((ASTNode) leftVal, (ASTNode) rightVal)) { 
        return false; 
       } 
      } else if (property.isChildListProperty()) { 
       Iterator<ASTNode> leftValIt = ((Iterable<ASTNode>) leftVal) 
         .iterator(); 
       Iterator<ASTNode> rightValIt = ((Iterable<ASTNode>) rightVal) 
         .iterator(); 
       while (leftValIt.hasNext() && rightValIt.hasNext()) { 
        // recursively call this function on child nodes 
        if (!equals(leftValIt.next(), rightValIt.next())) { 
         return false; 
        } 
       } 
       // one of the value lists have additional elements 
       if (leftValIt.hasNext() || rightValIt.hasNext()) { 
        return false; 
       } 
      } 
     } 
     return true; 
    } 
}