Skip to content

Commit

Permalink
make all tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
ftomassetti committed Jul 24, 2018
1 parent c7a4193 commit 741bb67
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 33 deletions.
Expand Up @@ -14,7 +14,13 @@
public class NameLogic { public class NameLogic {


public static boolean isAName(Node node) { public static boolean isAName(Node node) {
return node instanceof SimpleName || node instanceof Name || node instanceof ClassOrInterfaceType; if (node instanceof FieldAccessExpr) {
FieldAccessExpr fieldAccessExpr = (FieldAccessExpr)node;
return isAName(fieldAccessExpr.getScope());
} else {
return node instanceof SimpleName || node instanceof Name
|| node instanceof ClassOrInterfaceType || node instanceof NameExpr;
}
} }


public static NameRole classifyRole(Node name) { public static NameRole classifyRole(Node name) {
Expand Down Expand Up @@ -116,10 +122,18 @@ private static NameCategory reclassificationOfContextuallyAmbiguousNames(Node na
* Most users do not want to call directly this method but call classifyReference instead. * Most users do not want to call directly this method but call classifyReference instead.
*/ */
public static NameCategory syntacticClassificationAccordingToContext(Node name) { public static NameCategory syntacticClassificationAccordingToContext(Node name) {

if (name.getParentNode().isPresent()) {
Node parent = name.getParentNode().get();
if (isAName(parent) && nameAsString(name).equals(nameAsString(parent))) {
return syntacticClassificationAccordingToContext(parent);
}
}

if (isSyntacticallyATypeName(name)) { if (isSyntacticallyATypeName(name)) {
return NameCategory.TYPE_NAME; return NameCategory.TYPE_NAME;
} }
if (isSyntacticallyAExpressionName(name)) { if (isSyntacticallyAnExpressionName(name)) {
return NameCategory.EXPRESSION_NAME; return NameCategory.EXPRESSION_NAME;
} }
if (isSyntacticallyAMethodName(name)) { if (isSyntacticallyAMethodName(name)) {
Expand All @@ -138,23 +152,51 @@ public static NameCategory syntacticClassificationAccordingToContext(Node name)
return NameCategory.PACKAGE_NAME; return NameCategory.PACKAGE_NAME;
} }


if (name instanceof NameExpr) {
return NameCategory.EXPRESSION_NAME;
}
if (name instanceof FieldAccessExpr) {
return NameCategory.EXPRESSION_NAME;
}
if (name instanceof ClassOrInterfaceType) {
return NameCategory.TYPE_NAME;
}
if (name.getParentNode().isPresent() && name.getParentNode().get() instanceof ClassOrInterfaceType) {
return NameCategory.TYPE_NAME;
}
if (name.getParentNode().isPresent() && name.getParentNode().get() instanceof FieldAccessExpr) {
return NameCategory.EXPRESSION_NAME;
}

throw new UnsupportedOperationException("Unable to classify category of name contained in " throw new UnsupportedOperationException("Unable to classify category of name contained in "
+ name.getParentNode().get().getClass().getSimpleName()); + name.getParentNode().get().getClass().getSimpleName() + ". See " + name + " at " + name.getRange());
} }


private static boolean isSyntacticallyAAmbiguousName(Node name) { private static boolean isSyntacticallyAAmbiguousName(Node name) {
// A name is syntactically classified as an AmbiguousName in these contexts: // A name is syntactically classified as an AmbiguousName in these contexts:
// //
// 1. To the left of the "." in a qualified ExpressionName // 1. To the left of the "." in a qualified ExpressionName
//
if (whenParentIs(FieldAccessExpr.class, name, (p, c) -> p.getScope() == c)) {
return true;
}

// 2. To the left of the rightmost . that occurs before the "(" in a method invocation expression // 2. To the left of the rightmost . that occurs before the "(" in a method invocation expression
//
if (whenParentIs(MethodCallExpr.class, name, (p, c) -> p.getScope().isPresent() && p.getScope().get() == c)) {
return true;
}

// 3. To the left of the "." in a qualified AmbiguousName // 3. To the left of the "." in a qualified AmbiguousName
// //
// 4. In the default value clause of an annotation type element declaration (§9.6.2) // 4. In the default value clause of an annotation type element declaration (§9.6.2)
// //
// 5. To the right of an "=" in an an element-value pair (§9.7.1) // 5. To the right of an "=" in an an element-value pair (§9.7.1)
//
if (whenParentIs(MemberValuePair.class, name, (p, c) -> p.getValue() == c)) {
return true;
}

// 6. To the left of :: in a method reference expression (§15.13) // 6. To the left of :: in a method reference expression (§15.13)
return false; return false;
} }
Expand Down Expand Up @@ -274,6 +316,10 @@ private static boolean isSyntacticallyATypeName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(ImportDeclaration.class, name, (importDecl, c2) ->
importDecl.isStatic() && !importDecl.isAsterisk() && importDecl.getName() == c2)) {
return true;
}


// 4. To the left of the . in a static-import-on-demand declaration (§7.5.4) // 4. To the left of the . in a static-import-on-demand declaration (§7.5.4)


Expand Down Expand Up @@ -308,6 +354,10 @@ private static boolean isSyntacticallyATypeName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(ThisExpr.class, name, (ne, c2) ->
ne.getClassExpr().isPresent() && ne.getClassExpr().get() == c2)) {
return true;
}


// 9. To the left of .super in a qualified superclass field access expression (§15.11.2) // 9. To the left of .super in a qualified superclass field access expression (§15.11.2)


Expand All @@ -317,6 +367,10 @@ private static boolean isSyntacticallyATypeName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(SuperExpr.class, name, (ne, c2) ->
ne.getClassExpr().isPresent() && ne.getClassExpr().get() == c2)) {
return true;
}


// 10. To the left of .Identifier or .super.Identifier in a qualified method invocation expression (§15.12) // 10. To the left of .Identifier or .super.Identifier in a qualified method invocation expression (§15.12)
// //
Expand Down Expand Up @@ -458,7 +512,7 @@ private static boolean isSyntacticallyATypeName(Node name) {
return false; return false;
} }


private static boolean isSyntacticallyAExpressionName(Node name) { private static boolean isSyntacticallyAnExpressionName(Node name) {
// A name is syntactically classified as an ExpressionName in these contexts: // A name is syntactically classified as an ExpressionName in these contexts:
// //
// 1. As the qualifying expression in a qualified superclass constructor invocation (§8.8.7.1) // 1. As the qualifying expression in a qualified superclass constructor invocation (§8.8.7.1)
Expand All @@ -469,6 +523,10 @@ private static boolean isSyntacticallyAExpressionName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(ExplicitConstructorInvocationStmt.class, name, (ne, c2) ->
ne.getExpression().isPresent() && ne.getExpression().get() == c2)) {
return true;
}


// 2. As the qualifying expression in a qualified class instance creation expression (§15.9) // 2. As the qualifying expression in a qualified class instance creation expression (§15.9)


Expand All @@ -478,6 +536,10 @@ private static boolean isSyntacticallyAExpressionName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(ObjectCreationExpr.class, name, (ne, c2) ->
ne.getScope().isPresent() && ne.getScope().get() == c2)) {
return true;
}


// 3. As the array reference expression in an array access expression (§15.10.3) // 3. As the array reference expression in an array access expression (§15.10.3)


Expand All @@ -487,6 +549,10 @@ private static boolean isSyntacticallyAExpressionName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(ArrayAccessExpr.class, name, (ne, c2) ->
ne.getName() == c2)) {
return true;
}


// 4. As a PostfixExpression (§15.14) // 4. As a PostfixExpression (§15.14)


Expand All @@ -496,6 +562,10 @@ private static boolean isSyntacticallyAExpressionName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(UnaryExpr.class, name, (ne, c2) ->
ne.getExpression() == c2 && ne.isPostfix())) {
return true;
}


// 5. As the left-hand operand of an assignment operator (§15.26) // 5. As the left-hand operand of an assignment operator (§15.26)


Expand All @@ -505,6 +575,10 @@ private static boolean isSyntacticallyAExpressionName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(AssignExpr.class, name, (ne, c2) ->
ne.getTarget() == c2)) {
return true;
}


// 6. As a VariableAccess in a try-with-resources statement (§14.20.3) // 6. As a VariableAccess in a try-with-resources statement (§14.20.3)


Expand All @@ -524,6 +598,18 @@ private static boolean isSyntacticallyAExpressionName(Node name) {
)) { )) {
return true; return true;
} }
if (whenParentIs(TryStmt.class, name, (ne, c2) ->
ne.getResources().contains(c2))) {
return true;
}
if (whenParentIs(VariableDeclarator.class, name, (p2, c2) ->
p2.getInitializer().isPresent() && p2.getInitializer().get() == c2 && whenParentIs(VariableDeclarationExpr.class, p2, (p3, c3) ->
p3.getVariables().contains(c3) && whenParentIs(TryStmt.class, p3, (p4, c4) ->
p4.getResources().contains(c4)
)
))) {
return true;
}


return false; return false;
} }
Expand All @@ -538,6 +624,15 @@ public static String nameAsString(Node name) {
return ((SimpleName) name).getIdentifier(); return ((SimpleName) name).getIdentifier();
} else if (name instanceof ClassOrInterfaceType) { } else if (name instanceof ClassOrInterfaceType) {
return ((ClassOrInterfaceType) name).asString(); return ((ClassOrInterfaceType) name).asString();
} else if (name instanceof FieldAccessExpr) {
FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) name;
if (isAName(fieldAccessExpr.getScope())) {
return nameAsString(fieldAccessExpr.getScope()) + "." + nameAsString(fieldAccessExpr.getName());
} else {
throw new IllegalArgumentException();
}
} else if (name instanceof NameExpr) {
return ((NameExpr)name).getNameAsString();
} else { } else {
throw new UnsupportedOperationException("Unknown type of name found: " + name + " (" throw new UnsupportedOperationException("Unknown type of name found: " + name + " ("
+ name.getClass().getCanonicalName() + ")"); + name.getClass().getCanonicalName() + ")");
Expand Down
Expand Up @@ -5,6 +5,8 @@
import com.github.javaparser.ast.Node; import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Name; import com.github.javaparser.ast.expr.Name;
import com.github.javaparser.ast.expr.SimpleName; import com.github.javaparser.ast.expr.SimpleName;
import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest; import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest;
import org.junit.Test; import org.junit.Test;


Expand Down Expand Up @@ -201,35 +203,66 @@ public void returnTypeTypeName() {
} }


@Test @Test
public void annotationMemberTypeTypeName() { public void qualifiedAnnotationMemberTypeTypeName() {
assertNameInCodeIsSyntactically("@interface MyAnno { bar.MyClass myMember(); }", "bar.MyClass", assertNameInCodeIsSyntactically("@interface MyAnno { bar.MyClass myMember(); }", "bar.MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT); NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
} }


@Test
public void unqualifiedAnnotationMemberTypeTypeName() {
assertNameInCodeIsSyntactically("@interface MyAnno { MyClass myMember(); }", "MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
}

@Test @Test
public void throwClauseMethodTypeName() { public void throwClauseMethodTypeName() {
assertNameInCodeIsSyntactically("class Foo { void myMethod() throws bar.MyClass {} }", "bar.MyClass", assertNameInCodeIsSyntactically("class Foo { void myMethod() throws bar.MyClass {} }", "bar.MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT); NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
} }


@Test @Test
public void throwClauseConstructorTypeName() { public void qualifiedThrowClauseConstructorTypeName() {
assertNameInCodeIsSyntactically("class Foo { Foo() throws bar.MyClass {} }", "bar.MyClass", assertNameInCodeIsSyntactically("class Foo { Foo() throws bar.MyClass {} }", "bar.MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT); NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
} }


@Test @Test
public void fieldTypeTypeName() { public void unualifiedThrowClauseConstructorTypeName() {
assertNameInCodeIsSyntactically("class Foo { Foo() throws MyClass {} }", "MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
}

@Test
public void qualifiedFieldTypeTypeName() {
assertNameInCodeIsSyntactically("class Foo { bar.MyClass myField; }", "bar.MyClass", assertNameInCodeIsSyntactically("class Foo { bar.MyClass myField; }", "bar.MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT); NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
} }


@Test @Test
public void formalParameterOfMethodTypeName() { public void fieldTypeTypeNameSecondAttempt() {
assertNameInCodeIsSyntactically("public class JavaParserInterfaceDeclaration extends AbstractTypeDeclaration implements InterfaceDeclaration {\n" +
"private TypeSolver typeSolver; }", "TypeSolver",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
}

@Test
public void unqualifiedFieldTypeTypeName() {
assertNameInCodeIsSyntactically("class Foo { MyClass myField; }", "MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
}

@Test
public void qualifiedFormalParameterOfMethodTypeName() {
assertNameInCodeIsSyntactically("class Foo { void myMethod(bar.MyClass param) {} }", "bar.MyClass", assertNameInCodeIsSyntactically("class Foo { void myMethod(bar.MyClass param) {} }", "bar.MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT); NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
} }


@Test
public void unqualifiedFormalParameterOfMethodTypeName() {
assertNameInCodeIsSyntactically("class Foo { void myMethod(MyClass param) {} }", "MyClass",
NameCategory.TYPE_NAME, ParseStart.COMPILATION_UNIT);
}

@Test @Test
public void receiverParameterOfMethodTypeName() { public void receiverParameterOfMethodTypeName() {
assertNameInCodeIsSyntactically("void myMethod(Foo this) {}", "Foo", assertNameInCodeIsSyntactically("void myMethod(Foo this) {}", "Foo",
Expand Down Expand Up @@ -355,5 +388,46 @@ public void typeImportOnDemandPackageOrTypeName() {
assertNameInCodeIsSyntactically("import a.B.*;", "a.B", assertNameInCodeIsSyntactically("import a.B.*;", "a.B",
NameCategory.PACKAGE_OR_TYPE_NAME, ParseStart.COMPILATION_UNIT); NameCategory.PACKAGE_OR_TYPE_NAME, ParseStart.COMPILATION_UNIT);
} }

@Test
public void leftOfExpressionNameAmbiguousName() {
assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a.b.c",
NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a.b",
NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.anExpression[0]; } } ", "a",
NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
}

@Test
public void leftOfMethodCallAmbiguousName() {
assertNameInCodeIsSyntactically("class Bar { Bar() { a.b.c.aMethod(); } } ", "a.b.c",
NameCategory.AMBIGUOUS_NAME, ParseStart.COMPILATION_UNIT);
}

@Test
public void defaultValueTypeName() {
assertNameInCodeIsSyntactically("@RequestForEnhancement(\n" +
" id = 2868724,\n" +
" synopsis = \"Provide time-travel functionality\",\n" +
" engineer = \"Mr. Peabody\",\n" +
" date = anExpression" +
")\n" +
"public static void travelThroughTime(Date destination) { }",
"anExpression", NameCategory.AMBIGUOUS_NAME, ParseStart.CLASS_BODY);
}

// TODO unclear reading the JLS
// @Test
// public void methodReferenceAmbiguousName() {
// assertNameInCodeIsSyntactically("void myMethod() { Object o = a.b.c.Foo::myMethod; }", "a.b.c.Foo",
// NameCategory.TYPE_NAME, ParseStart.CLASS_BODY);
// assertNameInCodeIsSyntactically("void myMethod() { Object o = a.b.c.Foo::myMethod; }", "a.b.c",
// NameCategory.AMBIGUOUS_NAME, ParseStart.CLASS_BODY);
// assertNameInCodeIsSyntactically("void myMethod() { Object o = a.b.c.Foo::myMethod; }", "a.b",
// NameCategory.AMBIGUOUS_NAME, ParseStart.CLASS_BODY);
// assertNameInCodeIsSyntactically("void myMethod() { Object o = a.b.c.Foo::myMethod; }", "a",
// NameCategory.AMBIGUOUS_NAME, ParseStart.CLASS_BODY);
// }


} }

0 comments on commit 741bb67

Please sign in to comment.