diff --git a/src/main/java/spoon/reflect/reference/CtExecutableReference.java b/src/main/java/spoon/reflect/reference/CtExecutableReference.java index a5c15496ef1..45ad951182f 100644 --- a/src/main/java/spoon/reflect/reference/CtExecutableReference.java +++ b/src/main/java/spoon/reflect/reference/CtExecutableReference.java @@ -32,6 +32,8 @@ public interface CtExecutableReference extends CtReference, CtGenericElementR String CONSTRUCTOR_NAME = ""; + String UNKNOWN_TYPE = ""; + /** * Tells if this is a reference to a constructor. */ diff --git a/src/main/java/spoon/support/visitor/SignaturePrinter.java b/src/main/java/spoon/support/visitor/SignaturePrinter.java index 7395488be8a..058ee3bfebb 100644 --- a/src/main/java/spoon/support/visitor/SignaturePrinter.java +++ b/src/main/java/spoon/support/visitor/SignaturePrinter.java @@ -298,7 +298,11 @@ public void visitCtExecutableReference(CtExecutableReference reference) { write("("); if (reference.getParameters().size() > 0) { for (CtTypeReference param : reference.getParameters()) { - scan(param); + if (param != null && !"null".equals(param.getSimpleName())) { + scan(param); + } else { + write(CtExecutableReference.UNKNOWN_TYPE); + } write(", "); } clearLast(); diff --git a/src/test/java/spoon/test/signature/SignatureTest.java b/src/test/java/spoon/test/signature/SignatureTest.java index bcfd91a8d5c..78ca1e199d2 100644 --- a/src/test/java/spoon/test/signature/SignatureTest.java +++ b/src/test/java/spoon/test/signature/SignatureTest.java @@ -6,6 +6,7 @@ import org.junit.Test; import java.util.HashSet; +import java.util.List; import spoon.Launcher; import spoon.compiler.SpoonCompiler; @@ -20,6 +21,9 @@ import spoon.reflect.declaration.CtMethod; import spoon.reflect.factory.Factory; import spoon.reflect.factory.FactoryImpl; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.visitor.Query; +import spoon.reflect.visitor.filter.ReferenceTypeFilter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.support.DefaultCoreFactory; import spoon.support.StandardEnvironment; @@ -59,12 +63,12 @@ public void testNullSignature() throws Exception { @Test public void testNullSignatureInUnboundVariable() throws Exception { - //Unbound variable access bug fix: - //Bug description: The signature printer ignored the element Unbound variable reference + //Unbound variable access bug fix: + //Bug description: The signature printer ignored the element Unbound variable reference //(as well all Visitor that extend CtVisitor) //Fix description: modify CtVisitor (including SignaturePrinter) for visiting unbound variable access. - - + + Factory factory = new Launcher().createFactory(); // We want to compile a class with an reference to a class that is not // in the classpath @@ -85,7 +89,7 @@ public void testNullSignatureInUnboundVariable() throws Exception { // Must fail due to the unbound element "Complex.I" } CtClass clazz1 = (CtClass) factory.Type().getAll().get(0); - + CtMethod method = (CtMethod) clazz1.getAllMethods().toArray()[0]; CtInvocation invo = (CtInvocation) method.getBody().getStatement(0); @@ -101,7 +105,7 @@ public void testNullSignatureInUnboundVariable() throws Exception { assertTrue(unboundVarAccess.equals(toStringUnbound)); } - + @Test public void testLiteralSignature(){ Factory factory = new FactoryImpl(new DefaultCoreFactory(), @@ -109,68 +113,68 @@ public void testLiteralSignature(){ String stConstant = "\"hello\""; CtStatement sta1 = (factory).Code().createCodeSnippetStatement("System.out.println("+stConstant+")") .compile(); - + CtStatement sta2 = (factory).Code().createCodeSnippetStatement("String hello =\"t1\"; System.out.println(hello)") .compile(); - + CtStatement sta2bis = ((CtBlock)sta2.getParent()).getStatement(1); - + String signature1 = sta1.getSignature(); String signature2 = sta2bis.getSignature(); - + assertFalse(signature1.equals(signature2)); assertFalse(sta1.equals(sta2bis)); - + String signatureParameterWithQuotes = ((CtInvocation)sta1).getArguments().get(0).getSignature(); assertEquals(stConstant,signatureParameterWithQuotes); - + CtStatement stb1 = (factory).Code().createCodeSnippetStatement("Integer.toBinaryString(20)") .compile(); - + String signatureParameterWithoutQuotes = ((CtInvocation)stb1).getArguments().get(0).getSignature(); assertEquals("20",signatureParameterWithoutQuotes); } - + @Test public void testMethodInvocationSignatureStaticFieldsVariables(){ Factory factory = new FactoryImpl(new DefaultCoreFactory(), new StandardEnvironment()); CtStatement sta1 = (factory).Code().createCodeSnippetStatement("Integer.toBinaryString(Integer.MAX_VALUE)") .compile(); - + CtStatement sta2 = (factory).Code().createCodeSnippetStatement("Integer.toBinaryString(Integer.MIN_VALUE)") .compile(); - + String signature1 = sta1.getSignature(); String signature2 = sta2.getSignature(); - + assertFalse(signature1.equals(signature2)); assertFalse(sta1.equals(sta2)); - - + + CtStatement stb1 = (factory).Code().createCodeSnippetStatement("Integer.toBinaryString(20)") .compile(); - + CtStatement stb2 = (factory).Code().createCodeSnippetStatement("Integer.toBinaryString(30)") .compile(); - + assertFalse(stb1.equals(stb2)); assertFalse(sta1.getSignature().equals(sta2.getSignature())); - - + + CtStatement stc1 = (factory).Code().createCodeSnippetStatement("String.format(\"format1\",\"f2\" )") .compile(); - + CtStatement stc2 = (factory).Code().createCodeSnippetStatement("String.format(\"format2\",\"f2\" )") .compile(); - + assertFalse(stc2.equals(stc1)); assertFalse(stc2.getSignature().equals(stc1.getSignature())); - + } @Test public void testMethodInvocationSignatureWithVariableAccess() throws Exception{ - + Factory factory = new FactoryImpl(new DefaultCoreFactory(), new StandardEnvironment()); @@ -179,12 +183,12 @@ public void testMethodInvocationSignatureWithVariableAccess() throws Exception{ String content = "" + "class PR {" + "static String PRS = null;" - + + "public Object foo(String p) {" + " int s = 0; " + " this.foo(s);" + "this.foo(p);" - + " return null;" + + " return null;" + "}" + " public Object foo(int p) {" + " String s = null;" @@ -197,10 +201,10 @@ public void testMethodInvocationSignatureWithVariableAccess() throws Exception{ SpoonCompiler builder = new JDTSnippetCompiler(factory, content); builder.build(); - + CtClass clazz1 = (CtClass) factory.Type().getAll().get(0); assertNotNull(clazz1); - + //**FIRST PART: passing local variable access. ///--------From the first method we take the method invocations CtMethod methodString = (CtMethod) clazz1.getAllMethods().toArray()[0]; @@ -208,58 +212,58 @@ public void testMethodInvocationSignatureWithVariableAccess() throws Exception{ CtInvocation invoToInt1 = (CtInvocation) methodString.getBody().getStatement(1); String signatureInvoToInt = invoToInt1.getSignature(); CtExpression argumentToInt1 = invoToInt1.getArguments().get(0); - + //----------From the second method we take the Method Inv CtMethod methodInt = (CtMethod) clazz1.getAllMethods().toArray()[1]; CtInvocation invoToString = (CtInvocation) methodInt.getBody().getStatement(1); CtExpression argumentToString = invoToString.getArguments().get(0); - + String signatureInvoToString = invoToString.getSignature(); - //we compare the signatures of " this.foo(s);" from both methods + //we compare the signatures of " this.foo(s);" from both methods assertNotEquals(signatureInvoToInt, signatureInvoToString); - - + + //Now we check that we have two invocation to "foo(s)", - //but one invocation is with var 's' type integer, the other var 's' type int + //but one invocation is with var 's' type integer, the other var 's' type int String sigArgToInt1 = argumentToInt1.getSignature(); String sigArgToString1 = argumentToString.getSignature(); - + assertNotEquals(sigArgToInt1, sigArgToString1); - + /// ***SECOND PART, passing Parameters CtInvocation invoToString2 = (CtInvocation) methodString.getBody().getStatement(2); CtExpression argumentToString2 = invoToString2.getArguments().get(0); String signatureInvoToString2 = argumentToString2.getSignature(); - - + + CtInvocation invoToInt2 = (CtInvocation) methodInt.getBody().getStatement(2); CtExpression argumentToInt2 = invoToInt2.getArguments().get(0); String signatureInvoToInt2 = argumentToInt2.getSignature(); /// - + String sigParString = invoToString2.getSignature(); String sigParInteger = invoToInt2.getSignature(); - + //Compare the method invo signature (same real argument's name, different type) assertNotEquals(sigParString,sigParInteger); //Compare signature of parameters (same var name, different type) assertNotEquals(signatureInvoToString2,signatureInvoToInt2); - - + + } - + @Test public void testUnboundFieldSignature(){ - + Factory factory = new FactoryImpl(new DefaultCoreFactory(), new StandardEnvironment()); factory.getEnvironment().setNoClasspath(true); - + String content = "" + "class PR {" + "public Object foo(String p) {" + " this.mfield = p; " - + " return null;" + + " return null;" + "}" + "};"; @@ -271,24 +275,44 @@ public void testUnboundFieldSignature(){ catch(Exception e){ //must fail } - + CtClass clazz1 = (CtClass) factory.Type().getAll().get(0); assertNotNull(clazz1); - + //**FIRST PART: passing local variable access. ///--------From the first method we take the method invocations CtMethod methodString = (CtMethod) clazz1.getAllMethods().toArray()[0]; CtAssignment invoToInt1 = (CtAssignment) methodString.getBody().getStatement(0); - + String sigAssign = invoToInt1.getSignature(); - + CtExpression left = invoToInt1.getAssigned(); String sigleft = left.getSignature(); assertNotEquals("",sigleft.trim()); - + assertTrue(sigAssign.contains("")); - + + } + + @Test + public void testArgumentNotNullForExecutableReference() throws Exception { + final Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/variable/PropPanelUseCase_1.40.java"); + launcher.setSourceOutputDirectory("./target/trash"); + launcher.getEnvironment().setNoClasspath(true); + launcher.run(); + + final List references = Query.getReferences(launcher.getFactory(), new ReferenceTypeFilter(CtExecutableReference.class) { + @Override + public boolean matches(CtExecutableReference reference) { + return "addField".equals(reference.getSimpleName()) && super.matches(reference); + } + }); + assertEquals("#addField(, )", references.get(0).getSignature()); + assertEquals("#addField(, org.argouml.uml.ui.UMLComboBoxNavigator)", references.get(1).getSignature()); + for (CtExecutableReference reference : references) { + assertNotEquals("#addField(null, null)", reference.getSignature()); + } } - }