Giter VIP home page Giter VIP logo

inria / spoon Goto Github PK

View Code? Open in Web Editor NEW
1.7K 57.0 338.0 34.5 MB

Spoon is a metaprogramming library to analyze and transform Java source code. :spoon: is made with :heart:, :beers: and :sparkles:. It parses source files to build a well-designed AST with powerful analysis and transformation API.

Home Page: http://spoon.gforge.inria.fr/

License: Other

Java 99.40% HTML 0.01% Python 0.33% FreeMarker 0.05% Shell 0.12% Nix 0.10%
code-analysis code-transformation metaprogramming code-generation abstract-syntax-tree ast static-analysis compile-time-reflection java java9

spoon's People

Contributors

alcides avatar algomaster99 avatar andrewbwogi avatar arnobl avatar cnoguera avatar danglotb avatar egor18 avatar gerardpaligot avatar i-al-istannen avatar lakshyaaagrawal avatar leventov avatar martinezmatias avatar martinwitt avatar mkforsb avatar monperrus avatar msteinbeck avatar nharrand avatar petitpre avatar pvojtechovsky avatar renovate[bot] avatar rohitesh-kumar-jain avatar sirywell avatar slarse avatar strum355 avatar surli avatar swolf91 avatar tdurieux avatar tenax66 avatar xzel23 avatar zielint0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spoon's Issues

Processor for a specific type is invoked for wrong types

I've got an interface Animal and I'd like to write a processor for any class that implements the Animal interface. Thought I could get this done with:

public class AnimalTypeProcessor extends AbstractProcessor<CtType<Animal>> { 

 public void process(CtType<Animal> animalType) { ...}
}

This processor is being invoked for plenty of classes... none of them are the classes I'm interested in.

december release

Hi all,

The next release of Spoon is planned for Dec. 9.

It will include support for analyzing and transforming Java 7.

--Martin

StandardEnvironment clashes with my project's interests

i am instrumenting a project X which needs a classpath W, which is a chain of jar packages Y. i give SpoonCompiler the classpath Y so it can compile project X when creating the spoon model. however, there is a verification in StandardEnvironment.verifySourceClasspath() that clashes with project X's classpath.

the problem is that there are sources (*.java files) inside some jar file of Y, but StandardEnvironment doesn't like this. can we soften the verification? is it crucial for Spoon?

Java 8 Support

A project of mine was recently updated to Java 8 and we wanted to start using spoon for some static source code analysis. That reminded me that spoon doesn't support this yet. I read somewhere, that it's planned, but no concrete dates or anything.

So long story short: Is there any progress on the Java 8 front?

Import of an inner class in a class package

I found a new bug with imports of inner classes in a specific case.

We have 3 classes :

The first one is a super class with an inner class protected and with a visibility package.

class SuperClass {
    protected class InnerClassProtected {
    }
}

The second is a child class which extends the SuperClass.

public class ChildClass extends SuperClass {
}

And the third is a "client" class which extends the child class and with an inner class which extends the inner class (InnerClassProtected) of the SuperClass class.

public class ClientClass extends ChildClass {
    private class InnerClass extends InnerClassProtected {
    }
}

The last class works when the import of the InnerClassProtected is spoon.test.imports.testclasses.internal.ChildClass but spoon generates the output below:

public class ClientClass extends spoon.test.imports.testclasses.internal.ChildClass {
    private class InnerClass extends spoon.test.imports.testclasses.internal.SuperClass.InnerClassProtected {    }
}

The visibility of SuperClass is package so ClientClass can't access to the InnerClassProtected.

Bug in getReferencedTypes

it seems that AudioFormat.Encoding dependency is not detected by getReferencedTypes

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import java.util.HashMap;

public class Bar {
    public AudioFormat doSomething() {
        return new AudioFormat(Encoding.ALAW, (float)1.0, 8, 2, 1, (float)1.0, true, new HashMap<String, Object>());
    }
}

compile with java 1.6 or lower

I would like that spoon compiles with java 1.6 or better java 1.5.

Is there a special reason for using java 1.7? How about make spoon compile with older versions of java?

Unable to get the unresolved signature for a method with generic parameters

Hi,

When I explore references of a CtExecutable object, I am not able to get the unresolved method signature for a method with generic parameters (i.e. I am only able to get the signature with resolved types).

To illustrate the bug, let imagine such a class:

public class ClassWithGenericStaticMethod{
    public static <L> void aStaticMethod(Class<L> param1, L param2) {
        // my function...
    }

    public void aMethod(){
        String test = "";
        ClassWithGenericStaticMethod.aStaticMethod(String.class, test);
    }
}

Let type be a CtClass variable. I can explore the class references using:

List<CtReference> refs = Query.getReferences(type, 
    new AbstractReferenceFilter<CtReference>(CtReference.class){

    public boolean matches(CtReference reference) {
        return true;
    }
});

for(CtReference aReference : refs){
    if (aReference.toString().contains("aStaticMethod")) {
        // Here, aReference is equivallent to 

        if(aReference.getDeclaration() == null){
            System.out.println("Bad return value !");
        }
    }
}

I am able to get the method signature with resolved type (here
ClassWithGenericStaticMethod.aStaticMethod(java.lang.Class<java.lang.String>, java.lang.String)), but unable to get the unresolved signature, which I should obtain using aReference.getDeclaration(), but this method return null.

I created a test case on my spoon fork if needed.

Test failed in some environments for testSnippetFullClass in StringLiteralTest

I noticed that the method testSnippetFullClass in StringLiteralTest test class failed in some environments. You can see this class here: https://github.com/INRIA/spoon/blob/master/src/test/java/spoon/test/strings/StringLiteralTest.java.

So, in my environment, this test failed and the output is:

Failed tests:   testSnippetFullClass(spoon.test.strings.StringLiteralTest): expected:<...a.lang.String f3 = "[?]";> but was:<...a.lang.String f3 = "[?]";>

Weird, strings seems to be equals but JUnit isn't agree. When we look at the class, the problem is the dollar character. But, all the class is strange: we have 6 variables in the snippet, we retrieve 6 fields but we test 4 of them and comments below aren't reassuring.

When I print fields, I have these results:

java.lang.String f0 = "toto";
java.lang.String f1 = "\n";
java.lang.String f2 = "?";
java.lang.String f3 = "?";
java.lang.String f4 = "\t";
java.lang.String f5 = "\t";

I suspect previous bugs like mine and the previous contributor just remove embarrassing asserts.

Duplicate methods named spliterator

Dear all,

I'm encountering the following issue when running the tests from the current master branch.

Basically spoon.test.generics.BugCollection.testBugCommonCollection() fails with error

Duplicate methods named spliterator with the parameters () and () are inherited from the types Set<Map.Entry<K,V>> and Collection<Map.Entry<K,V>>

See full stack trace below. Note that although the test is run under Eclipse, the same issue occurs when running it with Maven from the command line.

My version of Java (in any case it would matter):

java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

Does anyone else bump into the same issue? Or am I the only one?

Thanks,
Lionel.

spoon.compiler.ModelBuildingException: Duplicate methods named spliterator with the parameters () and () are inherited from the types Set<Map.Entry<K,V>> and Collection<Map.Entry<K,V>> at /Users/seinturi/share/git/spoon/src/test/java/spoon/test/generics/BugCollection.java:35
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.report(JDTBasedSpoonCompiler.java:489)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.reportProblems(JDTBasedSpoonCompiler.java:504)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.build(JDTBasedSpoonCompiler.java:464)
at spoon.test.TestUtils.build(TestUtils.java:24)
at spoon.test.generics.GenericsTest.testBugCommonCollection(GenericsTest.java:167)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Bug when retrieving annotation parameter values that are of type array

Dear all,

I've bumped into a bug when trying to retrieve the value of an annotation parameter that is of type array.

I've exhibited the bug in the following branch: https://github.com/seintur/spoon/tree/annotation_values_bug

I do not have already a fix, although I've started debugging the code to understand what's going on.

Basically, my branch extends the existing Bound annotation type in spoon.test.annotation with the value() parameter that is of type String[]:

@target(ElementType.PARAMETER)
public @interface Bound {
int max() default 10;
String[] values();
}

The annotation is used with the following values: @bound(max = 8,values={"foo","bar"})

Then, at the end of testModelBuildingAnnotationBoundUsage(), I am simply trying to remove the value of the parameter with actualAnnotation.values().

Spoon fails with exception:

java.lang.ArrayStoreException: spoon.support.reflect.code.CtNewArrayImpl
at spoon.support.reflect.declaration.CtAnnotationImpl.getElementValue(CtAnnotationImpl.java:279)
at spoon.support.reflect.declaration.CtAnnotationImpl$AnnotationInvocationHandler.invoke(CtAnnotationImpl.java:71)
at com.sun.proxy.$Proxy2.values(Unknown Source)
at spoon.test.annotation.AnnotationTest.testModelBuildingAnnotationBoundUsage(AnnotationTest.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Lionel.

Declaration of an executable reference is null in anonymous class

I analyze this code :

package todel;

public class Foo {

    public class Bar {

    }

    public Bar getBar(){
        return new Bar(){
            public void printString(String myArg){
                System.out.println(myArg);
            }
        };
    }   
}

with this processor :

processorManager.addProcessor(new AbstractProcessor<CtVariableAccess>() {

    @Override
    public void process(CtVariableAccess arg0) {

        CtVariableReference varRef = arg0.getVariable();

        if(varRef instanceof CtParameterReference){

            CtParameterReference paramRef = (CtParameterReference) varRef;
            System.out.println("Parameter reference: "+paramRef);
            System.out.println("Declaring method reference: "+paramRef.getDeclaringExecutable());
            System.out.println("new Bar() type ref: "+paramRef.getDeclaringExecutable().getDeclaringType());
            System.out.println("new Bar() type declaration: "+paramRef.getDeclaringExecutable().getDeclaringType().getDeclaration());
            System.out.println("Foo type ref: "+paramRef.getDeclaringExecutable().getDeclaringType().getDeclaringType());

            System.out.println("Declaration of the Declaring method: "+paramRef.getDeclaringExecutable().getDeclaration());
            System.out.println(" "+paramRef.getDeclaration());
        }


    }
});

and I have this result:

Parameter reference: myArg
Declaring method reference: .printString
new Bar() type ref: 
new Bar() type declaration: null
Foo type ref: null
Declaration of the Declaring method: null
 null

The problem is that "paramRef.getDeclaration()" return null.
It seems that references to methods inside anonymous classes are incorrectly built.

Broken link on the home page of the web site

The technical presentation mentioned on the home page of the Spoon web site refers to

http://spoon.gforge.inria.fr/source-code-analysis-transformation-spoon.pdf

This link is currently broken.

Test Code isn't human readable because enums and static values are fully qualified

We're using spoon to generate some documentation. As part of this effort we're actually including some of the Java code in a generated website. We use CtMethod.getBody().toString() to get the code associated with a special annotated method. The string returned from this method has enums and other static variables fully qualified. Can this be disabled? The actual code itself (that's parsed by spoon) doesn't use fully qualified names to refer to enums (it relies on Java import mechanism). Could spoon by default return a faithful copy of the actual code?

Default value in inner annotation

I found a bug in the usage of default value when we use annotations with fields of array.

The annotation (below) can be declare at the root of a file or like inner class, but the output is different.

Annotation:

@Retention(value = RetentionPolicy.RUNTIME)
public @interface AnnotArray {
    public Class<?>[] value() default { };
}

The output:

public class AnnotArrayInnerClass {
    @java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
    public @interface Annotation {
        java.lang.Class<?>[] value() default new java.lang.Class<?>[]{  };
    }
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface AnnotArray {
    java.lang.Class<?>[] value() default {  };
}

We see when we declare the annotation in inner class, the output isn't valid and can't compile.

Illegal generic type for instanceof with spoon output

You have a class A with generic parameter, an static inner class B, an inner class in B, C and a method in B which checks if a Object is instance of C with the expression instanceof :

public class A<T>  {
  static class B<T> {
    class C {
    }
    public boolean m(Object o) {
      if (!(o instanceof A.B.C))
        return false;
      return true;
    }
  }
}

Spoon didn't generate a valid output and the compilator throws an error :

illegal generic type for instanceof

Source code generated:

public class A<T>  {
  static class B<T> {
    class C {
    }
    public boolean m(Object o) {
      if (!(o instanceof C))
        return false;
      return true;
    }
  }
}

spoon 1.5 disappeared from Maven central

Once upon a time spoon 1.5 was in maven central and all was well. At some point, Spoon 1.5 simply vanished. And

<dependency>
    <groupId>fr.inria.gforge.spoon</groupId>
    <artifactId>spoon-core</artifactId>
    <version>1.5</version>
</dependency>

No longer worked and all builds broke. Why did this happen? Is Maven Central running out of space? Why ever delete artifacts that have been exposed to the public?

This is especially problematic since later versions of spoon (2.4, 3.0) contain some significant issues around annotation processing (see #132, #60). Spoon 1.5 did not have these issues I think because, well, all our stuff used to work and now it doesn't.

I wonder if it might be possible to redeploy spoon 1.5 to maven central? It'd be much appreciated.

(Spoon is amazing btw. Please don't take this issue as a complaint, we'd like to upgrade at some point but not until the annotation issues have been resolved.)

String arrays for annotation values are not parsed correctly

Suppose you have an annotation:

public @interface Tags {
 public String[] value();
}

And then you use it:

@Tags(Tags.T1)
public void myMethod() {
}

Where T1 is a static final String contant.

When you attempt you process Tags at runtime, for example:

Tags tags = ctMethod.getAnnotation(Tags.class)
String[] tagValues = tags.value();

The second line will throw a ClassCastException saying String cannot be cast to LString;

New class of an inner class presents in a super and sub class

I found a new bug when we try to create a new class of an inner class presents in a super and sub class.

We have 2 classes. First, the SuperClass with an inner class Item and a constructor.

public class SuperClass {
    public static class Item {
        public Item(int i, String s) {
        }
    }
}

The second class, SubClass inherits of SuperClass and has also an inner class Item but with a constructor different and it inherits the inner class of the SuperClass.

public class SubClass extends SuperClass {
    public void aMethod() {
        new SubClass.Item("");
    }

    public static class Item extends SuperClass.Item {
        public Item(String s) {
            super(1, s);
        }
    }
}

When we spoones these classes, the statement in the body of the method aMethod in SubClass becomes:

new Item("");

This statement isn't valid. Java tries to use the class Item of SuperClass and don't want compile.

processing of annotations

I found a bug with the processing of annotations.
In my project I've a class AnnotationProcess which extends the AbstractProcessor<CtAnnotation<?>>

Imagine you've the following annotations:

public @interface OuterAnnotation
{
    public MiddleAnnotation[] value();
}

public @interface MiddleAnnotation
{
    public InnerAnnotation value();
}

public @interface InnerAnnotation
{
    public String value();
}

The processing of the InnerAnnotation doesn't work if the MiddleAnnotation is used as an array. So the processor isn't invoked with the InnerAnnotation.

examples:

@OuterAnnotation(@MiddleAnnotation(@InnerAnnotation("hello")))
public void test() // The InnerAnnotation will be processed
{}

@OuterAnnotation({@MiddleAnnotation(@InnerAnnotation("hello")), @MiddleAnnotation(@InnerAnnotation("hello again"))})
public void test2() // The InnerAnnotation won't be processed
{}

Expressions in arrays inside annotations cause IllegalArgumentException

Suppose I have a class like

public class TestClass {

    private static final String PREFIX = "my-prefix";

    @Produces({PREFIX + "-test-object-1",PREFIX + "-test-object-2"})
    public Object getObject(){
        return null;
    }
}

and I start processing it with processor like

public class TestProcessor extends AbstractProcessor<CtAnnotation<?>> {

    public void process(CtAnnotation<?> element) {
        Object elementValue = element.getElementValue("value");     
        System.out.println(elementValue.toString());
    }
}

then I receive an error:

java.lang.IllegalArgumentException: array element type mismatch
    at java.lang.reflect.Array.set(Native Method)
    at spoon.support.reflect.declaration.CtAnnotationImpl.convertValue(CtAnnotationImpl.java:212)
    at spoon.support.reflect.declaration.CtAnnotationImpl.getElementValue(CtAnnotationImpl.java:284)
    at org.raml.test.TestProcessor.process(TestProcessor.java:10)
    at org.raml.test.TestProcessor.process(TestProcessor.java:1)
    at spoon.support.visitor.ProcessingVisitor.scan(ProcessingVisitor.java:94)
    at spoon.support.visitor.ProcessingVisitor.scan(ProcessingVisitor.java:66)
    at spoon.reflect.visitor.CtScanner.visitCtMethod(CtScanner.java:469)

handling non-java resources

as the default Java compiler does, I propose that Spoon copies all non-Java files that are in the source folder to the output folder.

doing so, one can safely compile the output folder.

Bug in annotation value access

There are 2 ways to annotate an element with an array parameter:
@AnnotArray({ RuntimeException.class })
public void testValueWithArray() ;
@AnnotArray(RuntimeException.class)
public void testValueWithoutArray() ;

When I try to access to the annotation parameter with spoon with something like:
myCtMethod.getAnnotation(AnnotArray.class).value()

It work only with the first method example. The second fail with exception:
java.lang.ClassCastException: java.lang.Class cannot be cast to [Ljava.lang.Class;
at com.sun.proxy.$Proxy3.value(Unknown Source)

I've write a test that surround this bug:
https://github.com/petitpre/spoon/blob/bugValues/src/test/java/spoon/test/annotation/AnnotationTest.java#L345

Java 7: pretty-print diamond syntax

For the support of java 7, spoon must support diamond syntax. It support already (yeah!) but not totally. Here is an example to illustrate the "problem":

DiamondExample is a class ready to be spooned.

public class DiamondExample {
    public void col() {
        Collection<String> coll = new ArrayList<>();

        Collection<String> coll2 = new ArrayList();

        Collection<String> coll3 = new ArrayList<String>();
    }
}

The output of spoon is:

public class DiamondExample {
    public void col() {
        java.util.Collection<java.lang.String> coll = new java.util.ArrayList<java.lang.String>();
        java.util.Collection<java.lang.String> coll2 = new java.util.ArrayList();
        java.util.Collection<java.lang.String> coll3 = new java.util.ArrayList<java.lang.String>();
    }
}

So, when spoon detects a diamond syntax, it replaces with the right implementation. So the result is valid and support java 7 but the output isn't java 7.

Good thing or not? I would like reviews about this from the community. :)

No Maven Central release

I have currently the problem, that I can't deploy new versions of a project of mine to the Maven Central Repository, because it recently started using spoon. The problem is, that spoon in its current version is not available in Maven Central, but to be able to deploy an artifact all of its dependencies must be available in Maven Central themselves.
Our workaround will be to deploy a forked version of spoon with a changed pom.xml until the official version is available.

Avoid rewrite of untouched classes

If a class is processed but not modified, for example only analyzed for creating a new class, this class is anyway generated.
Provide a way to specify the classes to generate(or the classes to don't generate) could be a good improvement

testMain fails because of wrong regex

The testMain() of the MainTest class fails with an InvalidClassPathException.
It fails because of the wrong regex. The regex doesn't fit every use case. The test-classes entry could be the last entry too. In that case there isn't a : behind it.
Furthermore the : is hardcoded there. It doesn't use the JDTBasedSpoonCompiler.CLASSPATH_ELEMENT_SEPARATOR constant.

I see two ways to fix it.

  1. fix the regex. It should be something like:
systemClassPath = systemClassPath.replaceAll("(" + JDTBasedSpoonCompiler.CLASSPATH_ELEMENT_SEPARATOR + "|^)[^" + JDTBasedSpoonCompiler.CLASSPATH_ELEMENT_SEPARATOR + "]*test-classes(" + JDTBasedSpoonCompiler.CLASSPATH_ELEMENT_SEPARATOR + "|$)", "$1"); 

I really DON'T like this way.

  1. Do it this way:
StringBuilder classpath = new StringBuilder();
for (String classpathEntry : System.getProperty("java.class.path").split(JDTBasedSpoonCompiler.CLASSPATH_ELEMENT_SEPARATOR))
{
    if (!classpathEntry.contains("test-classes"))
    {
        classpath.append(classpathEntry);
        classpath.append(JDTBasedSpoonCompiler.CLASSPATH_ELEMENT_SEPARATOR);
    }
}
String systemClassPath = classpath.substring(0, classpath.length() - 1);

It's much more readable.

Fragment mode (-f) does not change code after Spoon Version 1.5

I am using the -f (fragment) mode of Spoon.

The processor is the same to that in the guide in http://spoon.gforge.inria.fr/Doc/FAQ/, (the part of "How to preserve the transformed source code formatting and one-line comments").

I found that only Spoon-1.5 can change the source code with the processor. But all the other spoon versions cannot make any change.
Is there any further steps to active the -f mode?

The commands that I used are as follows.
java -cp target/classes:spoon-core-3.1-jar-with-dependencies.jar spoon.Launcher -i src/test/java/com/mine/TempExample.java -p com.mine.TempExprProcessor -v --compliance 6 -f
java -cp target/classes:spoon-core-1.5-jar-with-dependencies.jar spoon.Launcher -i src/test/java/com/mine/TempExample.java -p com.mine.TempExprProcessor -v --compliance 6 -f

The processor is as follows.
public class TempExprProcessor extends AbstractProcessor{
public void process(CtExpression e) {
CompilationUnit cu=e.getPosition().getCompilationUnit();
SourceCodeFragment fragment = new SourceCodeFragment();
fragment.position = e.getPosition().getSourceStart();
fragment.replacementLength =
e.getPosition().getSourceEnd() - e.getPosition().getSourceStart();
fragment.code="...";
cu.addSourceCodeFragment(fragment);
}
}

add a common superclass between CtField and CtExecutable

CtField and CtExecutable both implement the method getDeclaringType().
is it convenient for anyone else to create an interface which could serve as a super class between both of them? i've seen this happens a lot in Spoon and it would save me to duplicate one method in my project.

my proposal: CtDeclaredElement

Java 7: pretty-print multi catch "catch (IndexOutOfBoundsException | UncheckedException)"

For the support of java 7, spoon must support multi catch. It support already (yeah!) but not totally. Here is an example to illustrate the "problem":

TryCatchExample is a class ready to be spooned.

public class TryCatchExample {
    public void method(String[] array) {
        try {
            if (array.length > 10) {
                throw new UncheckedException();
            }
            String firstItem = array[0];
            if ("error".equals(firstItem)) {
                throw new CheckedException();
            }
        } catch (IndexOutOfBoundsException | UncheckedException | CheckedException e) {
            e.printStackTrace();
        }
    }
}

The output of spoon is:

public class TryCatchExample {
    public void method(java.lang.String[] array) {
        try {
            if ((array.length) > 10) {
                throw new UncheckedException();
            } 
            java.lang.String firstItem = array[0];
            if ("error".equals(firstItem)) {
                throw new CheckedException();
            } 
        } catch (java.lang.IndexOutOfBoundsException e) {
            e.printStackTrace();
        } catch (UncheckedException e) {
            e.printStackTrace();
        } catch (CheckedException e) {
            e.printStackTrace();
        }
    }
}

So, when spoon detects a multi catch, it replaces with java 6 syntax. So the result is valid and support java 7 but the output isn't java 7.

Good thing or not? I would like reviews about this from the community. :)

template classpath

I asked it already but didn't get an answer.

What is the template classpath? What's the different between the template and the source classpath?
It definitely needs a better description.


Furthermore I recommend to fit the template classpath system to the source classpath one. So changing the method setTemplateClasspath(String classpath) to setTemplateClasspath(String... classpathEntries)

Type of arguments is missing in CtReference

When a processor process a CtExecutable on a class with some constructors (executables) whom reference others constructors in the same classe, a Query.getReference(...) on the current executable returns references without these arguments.

For example, a class MyClass with 3 constructors. The first constructor reference the second and the second reference the third.

public class MyClass {
    public MyClass() {
        this("Default");
    }

    public MyClass(String param) {
        this(param, 0);
    }

    public MyClass(String param, int paramint) {

    }
}

In the processor, when we retrieve all references of the current constructor, we can't know what is the constructor referenced because arguments aren't available in the interface of references.

public class MyProcessor extends AbstractProcessor<CtExecutable<?>>{

    public void process(CtExecutable<?> element) {

        List<CtReference> refs = Query.getReferences(element, new AbstractReferenceFilter<CtReference>(CtReference.class) {
            public boolean matches(CtReference reference) {
                return true;
            }
        });

        Set<CtReference> unduplicate = new HashSet<CtReference>(refs);

        for(CtReference aReference : unduplicate){
            // ...
        }
    }
}

February release

Hi all,

The February release (v3.1, bug fix) is planned for February 9.

--Martin

This invocation becomes super invocation after changing name of the enclosing class

We have a class AClass with 2 constructors and one of them referenced the other one with a this instruction:

public class AClass {
  private final String string;

  public AClass() {
    this("");
  }

  public AClass(String string) {
    this.string = string;
  }
}

When we would like rename the name of the CtClass, this("") becomes super(""). How can be possible? Well, in the DefaultJavaPrettyPrinter, we print this or super according to these conditions:

CtType<?> parentType = invocation.getParent(CtType.class);
if ((parentType != null) 
    && (parentType.getQualifiedName() != null)
    && parentType.getQualifiedName().equals(invocation.getExecutable().getDeclaringType().getQualifiedName())) {
  write("this");
} else {
  if (invocation.getTarget() != null) {
    write(invocation.getTarget().getSignature() + '.');
  }
  write("super");
}

The problem is that invocation.getExecutable().getDeclaringType().getQualifiedName() returns a CtTypeReference with the older name of the CtClass. So, the condition returns false and we print a super instruction.

improve logging system

At the moment just error messages are logged. How about logging at the debug and info level too? The user could set the log level. That would relieve the debugging process of spoon.

november release

Hi all,

The next release of Spoon is planned for November 12th. New features won't be merged as of Nov 5th.

Best regards,

--Martin

SwitchCaseTest not compiling with javac

The test case introduced by eab464a does not compile using the standard Java Compiler. It only compiles using the Eclipse Compiler.

The offending code section:

// this compiles (thanks to the new CtCase extends CtStatementList)
for (CtStatement s : c) {
    l.add(s);
}

The standard compiler seems to have problems detecting the generic type of the Iterable interface in that case. It detects Iterable even though it's Iterable).

Possible simple solutions/workarounds:

  • Casting c to Iterable in the for-each loop
  • Changing s' type to Object which works without additional changes as the the list is defined as a raw type.
  • Using c.getStatements() instead of just c

String Array Annotations are not being correctly parsed

There's an annotation:

@Retention(RetentionPolicy.RUNTIME)
public @interface Tags {

    public String[] value();
}

In several cases this annotation is used without actually defining an array. For example:

@Tags("Boom")
public void testMethod() {

}

Or sometimes it's used by referring to a single static constant:

@Tags(Tags.Boom)
public void testMethod() {
}

Attempts to retrieve this array later, when the annotation is declared using a single element result in a class cast exception:

2015-02-04 18:40:55,773 ERROR spoon.Launcher - java.lang.String cannot be cast to [Ljava.lang.String;
java.lang.ClassCastException: java.lang.String cannot be cast to [Ljava.lang.String;

Multi-typed catch variable

In the Java 7 multi-catch, the difference types of variable are no correctly imported :

try {
} catch(Exception1 | Exception2 e ){}

The type Exception2 are not added in generated imports

Classes with same name than classes in java.lang package

When you have classes named Double, Float or any classes contains in java.lang package and you want to generate the source code with imports, spoon use classes in java.lang package and not classes in the target project.

Reported by Carsten on the Spoon's mailing list.

classpath path separator

Due to a few commits from yesterday spoon takes the : as the separator within the classpath. Here is an API proof
Unfortunately the : doesn't work as the path separator. The character depends on the OS. Unix uses : as path separator and ; is used by Windows.
But the : has a different use case in windows paths. Every hard drive partition has a character at windows and the : is the separator between the partition and the path on the partition. For example: D:\this\is\the\path
so after splitting it, spoon recognizes two paths. D and \this\is\the\path, but that's just one path and the program would throw an InvalidClassPathException.

To solve the problem I recommend to use

public static final String CLASSPATH_ELEMENT_SEPARATOR = File.pathSeparator;

instead of that line.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.