Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sniper: unable to rename class #3097

Closed
tdurieux opened this issue Sep 11, 2019 · 3 comments · Fixed by #3418
Closed

sniper: unable to rename class #3097

tdurieux opened this issue Sep 11, 2019 · 3 comments · Fixed by #3418
Labels

Comments

@tdurieux
Copy link
Collaborator

Using this code:

final CtClass<?> ctClass = f.Class().get("spoon.test.prettyprinter.testclasses.Validation");
ctClass.setSimpleName("Test");

The model is correctly changed, but the sniper mode does not succeed to generate the correct output.

@monperrus
Copy link
Collaborator

Do you mean

  • only rename the class
  • or rename the class and all references (full-fledged refactoring)

@tdurieux
Copy link
Collaborator Author

tdurieux commented Nov 24, 2019

A full refactoring could be nice but here the problem is the the sniper mode does not change the name of the class. In the output the old name is still used.

@ITWOI
Copy link

ITWOI commented May 27, 2020

Hi, I have a similar problem. But it leads to NPE.

I use Spoon 8.1.0-beta-9.

Here is the code, note that if I remove launcher.getEnvironment().setPrettyPrinterCreator(() -> new SniperJavaPrettyPrinter(launcher.getEnvironment()));, then every thing works fine.

public class ClassRename extends AbstractProcessor<CtClass> {
    int renameIndex;
    public ClassRename(int renameIndex) {
        this.renameIndex = renameIndex;
    }
    @Override
    public void process(CtClass arg0) {
        String newMethodName = arg0.getSimpleName() + renameIndex;
        arg0.setSimpleName(newMethodName);
    }
}
   void entry(List<StmtTrace> ele, int index) {
        final Launcher launcher = retLauncher();
        launcher.addProcessor(new ClassRename(index));
        launcher.run();
    }
    Launcher retLauncher(){
        final Launcher launcher = new Launcher();
        launcher.setArgs(arg);
        launcher.getEnvironment().setPrettyPrinterCreator(() -> new SniperJavaPrettyPrinter(launcher.getEnvironment()));
        return launcher;
    }
Exception in thread "main" spoon.SpoonException: java.lang.NullPointerException
	at spoon.Launcher.prettyprint(Launcher.java:789)
	at spoon.Launcher.run(Launcher.java:725)
	at MutManager.callMut(MutManager.java:307)
	at MutManager.doMutate(MutManager.java:297)
	at MutManager.executeMutation(MutManager.java:184)
	at MutManager.runManager(MutManager.java:227)
	at Main.main(Main.java:71)
Caused by: java.lang.NullPointerException
	at spoon.support.reflect.declaration.CtCompilationUnitImpl.getMainType(CtCompilationUnitImpl.java:148)
	at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.generateProcessedSourceFilesUsingCUs(JDTBasedSpoonCompiler.java:517)
	at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.generateProcessedSourceFiles(JDTBasedSpoonCompiler.java:204)
	at spoon.Launcher.prettyprint(Launcher.java:787)

The reason of NPE is caused by the following code:

@Override
	public CtType<?> getMainType() {
		if (getFile() == null) {
			return getDeclaredTypes().get(0);
		}
		for (CtType<?> t : getDeclaredTypes()) {
			String name = getFile().getName();
			name = name.substring(0, name.lastIndexOf('.'));
			if (t.getSimpleName().equals(name)) {
				return t;
			}
		}

getDeclaredTypes() return a size 1 List but the element is null.

What I want to do is to remove some statements and rename the class, but I found that the generated code will have additional parentheses.

Here is an example (it is also the program triggered NPE),

 package src;
 public class Main {
     public static int m1(int arr[], int n) {
         for (int i = 0; i < n-1; i++) {
             for (int j = 0; j < n-i-1; j++) {
                 if (arr[j] > arr[j+1])
                 {
                     int temp = arr[j];
                     arr[j] = arr[j+1];
                     arr[j+1] = temp;
                 }
             }
         }
         return 0;
     }
 }

The generated code is:

 package src;
 public class Main2 {
     public static int m1(int[] arr, int n) {
         for (int i = 0; i < (n - 1); i++) {
             for (int j = 0; j < ((n - i) - 1); j++) {
                 if (arr[j] > arr[j + 1]) {
                     int temp = arr[j];
                     arr[j] = arr[j + 1];
                     arr[j + 1] = temp;
                 }
             }
         }
         return 0;
     }
 }

Is there any way to avoid introducing parentheses?

---update---

I found the program has "package src;" but the input dir doesn't relate to "src". When I removed "package src;", it doesn't crash but the output is strange:

 public class Main {
     public Main() {
     }

     public static void main(java.lang.String[] arg0) {
     }

     public static org.apache.commons.cli.CommandLine parseArg(java.lang.        String[] arg0) {
     }
 }

Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants