mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 10:18:46 +00:00
[fixes #3529] Set real field initializer source
Eclipse copies the field initializer source code if it is a constant. For generated nodes we have to read it from the ast node and not from the source file.
This commit is contained in:
1 parent
fd55c7aa93
commit
f277791cf0
7 files changed
+193
-3
No files matched your search
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2023 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2024 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -100,6 +100,7 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
|
||||
patchJavadoc(sm);
|
||||
patchASTConverterLiterals(sm);
|
||||
patchASTNodeSearchUtil(sm);
|
||||
patchFieldInitializer(sm);
|
||||
|
||||
patchPostCompileHookEcj(sm);
|
||||
|
||||
@@ -1029,6 +1030,42 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
|
||||
.build());
|
||||
}
|
||||
|
||||
private static void patchFieldInitializer(ScriptManager sm) {
|
||||
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
|
||||
.targetClass("org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor")
|
||||
.fieldName("$fieldInfo")
|
||||
.fieldType("Ljava/lang/Object;")
|
||||
.build());
|
||||
|
||||
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.addField()
|
||||
.targetClass("org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor")
|
||||
.fieldName("$sourceFieldElementInfo")
|
||||
.fieldType("Lorg/eclipse/jdt/internal/core/SourceFieldElementInfo;")
|
||||
.build());
|
||||
|
||||
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.exitEarly()
|
||||
.target(new MethodTarget("org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor", "exitField", "void", "int", "int", "int"))
|
||||
.decisionMethod(new Hook("lombok.launch.PatchFixesHider$FieldInitializer", "storeFieldInfo", "boolean", "org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor"))
|
||||
.request(StackRequest.THIS)
|
||||
.transplant()
|
||||
.build());
|
||||
|
||||
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapMethodCall()
|
||||
.target(new MethodTarget("org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor", "exitField", "void", "int", "int", "int"))
|
||||
.methodToWrap(new Hook("org.eclipse.jdt.internal.core.SourceFieldElementInfo", "<init>", "void"))
|
||||
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$FieldInitializer", "storeSourceFieldElementInfo", "void", "org.eclipse.jdt.internal.core.SourceFieldElementInfo", "org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor"))
|
||||
.requestExtra(StackRequest.THIS)
|
||||
.transplant()
|
||||
.build());
|
||||
|
||||
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
|
||||
.target(new MethodTarget("org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor", "exitField", "void", "int", "int", "int"))
|
||||
.wrapMethod(new Hook("lombok.launch.PatchFixesHider$FieldInitializer", "overwriteInitializer", "void", "org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor"))
|
||||
.request(StackRequest.THIS)
|
||||
.transplant()
|
||||
.build());
|
||||
}
|
||||
|
||||
private static void patchCrossModuleClassLoading(ScriptManager sm) {
|
||||
sm.addScriptIfWitness(OSGI_TYPES, ScriptBuilder.wrapReturnValue()
|
||||
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.parser.Parser", "<clinit>"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 The Project Lombok Authors.
|
||||
* Copyright (C) 2010-2024 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -52,7 +52,9 @@ import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
|
||||
import org.eclipse.jdt.core.dom.Type;
|
||||
import org.eclipse.jdt.core.search.SearchMatch;
|
||||
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor.FieldInfo;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Expression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
@@ -61,7 +63,9 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
|
||||
import org.eclipse.jdt.internal.compiler.parser.Parser;
|
||||
import org.eclipse.jdt.internal.core.CompilationUnitStructureRequestor;
|
||||
import org.eclipse.jdt.internal.core.SourceField;
|
||||
import org.eclipse.jdt.internal.core.SourceFieldElementInfo;
|
||||
import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
|
||||
import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
|
||||
import org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner;
|
||||
@@ -935,6 +939,68 @@ final class PatchFixesHider {
|
||||
}
|
||||
}
|
||||
|
||||
public static class FieldInitializer {
|
||||
public static final Field INFO_STACK;
|
||||
public static final Field FIELD_INFO;
|
||||
public static final Field SOURCE_FIELD_ELEMENT_INFO;
|
||||
public static final Field INITIALIZATION_SOURCE;
|
||||
public static final Field NODE;
|
||||
public static final boolean INITIALIZED;
|
||||
|
||||
static {
|
||||
INFO_STACK = Permit.permissiveGetField(CompilationUnitStructureRequestor.class, "infoStack");
|
||||
FIELD_INFO = Permit.permissiveGetField(CompilationUnitStructureRequestor.class, "$fieldInfo");
|
||||
SOURCE_FIELD_ELEMENT_INFO = Permit.permissiveGetField(CompilationUnitStructureRequestor.class, "$sourceFieldElementInfo");
|
||||
INITIALIZATION_SOURCE = Permit.permissiveGetField(SourceFieldElementInfo.class, "initializationSource");
|
||||
NODE = Permit.permissiveGetField(FieldInfo.class, "node");
|
||||
INITIALIZED = INFO_STACK != null && FIELD_INFO != null && SOURCE_FIELD_ELEMENT_INFO != null && INITIALIZATION_SOURCE != null && NODE != null;
|
||||
}
|
||||
|
||||
public static boolean storeFieldInfo(CompilationUnitStructureRequestor compilationUnitStructureRequestor) {
|
||||
try {
|
||||
if (INITIALIZED) {
|
||||
Stack<?> infoStack = Permit.get(INFO_STACK, compilationUnitStructureRequestor);
|
||||
Object fieldInfo = infoStack.peek();
|
||||
Permit.set(FIELD_INFO, compilationUnitStructureRequestor, fieldInfo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do not break eclipse
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static void storeSourceFieldElementInfo(SourceFieldElementInfo fieldInfo, CompilationUnitStructureRequestor compilationUnitStructureRequestor) {
|
||||
try {
|
||||
if (INITIALIZED) {
|
||||
Permit.set(SOURCE_FIELD_ELEMENT_INFO, compilationUnitStructureRequestor, fieldInfo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do not break eclipse
|
||||
}
|
||||
}
|
||||
|
||||
public static void overwriteInitializer(CompilationUnitStructureRequestor compilationUnitStructureRequestor) {
|
||||
try {
|
||||
if (INITIALIZED) {
|
||||
FieldInfo fieldInfo = Permit.get(FIELD_INFO, compilationUnitStructureRequestor);
|
||||
Permit.set(FIELD_INFO, compilationUnitStructureRequestor, null);
|
||||
|
||||
SourceFieldElementInfo sourceFieldElementInfo = Permit.get(SOURCE_FIELD_ELEMENT_INFO,compilationUnitStructureRequestor);
|
||||
Permit.set(SOURCE_FIELD_ELEMENT_INFO, compilationUnitStructureRequestor, null);
|
||||
|
||||
if (sourceFieldElementInfo.getInitializationSource() != null) {
|
||||
AbstractVariableDeclaration node = Permit.get(NODE, fieldInfo);
|
||||
|
||||
if (PatchFixes.isGenerated(node)) {
|
||||
Permit.set(INITIALIZATION_SOURCE, sourceFieldElementInfo, node.initialization.toString().toCharArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do not break eclipse
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tests {
|
||||
public static StringBuffer printMethod(AbstractMethodDeclaration methodDeclaration, int tab, StringBuffer output, TypeDeclaration type) {
|
||||
return (StringBuffer) printMethod(methodDeclaration, tab, (Object) output, type);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package pkg;
|
||||
|
||||
public @interface Annotation {
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package pkg;
|
||||
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
|
||||
@FieldNameConstants
|
||||
public class Constants {
|
||||
String test;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package pkg;
|
||||
|
||||
@Annotation(Constants.Fields.test)
|
||||
public class Usage {
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
import lombok.eclipse.cleanup.CleanupTest;
|
||||
import lombok.eclipse.compile.NoErrorsTest;
|
||||
import lombok.eclipse.edit.SelectTest;
|
||||
import lombok.eclipse.refactoring.ExtractInterfaceTest;
|
||||
import lombok.eclipse.refactoring.InlineTest;
|
||||
@@ -12,7 +13,7 @@ import lombok.eclipse.refactoring.RenameTest;
|
||||
import lombok.eclipse.references.FindReferencesTest;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ExtractInterfaceTest.class, RenameTest.class, SelectTest.class, CleanupTest.class, FindReferencesTest.class, InlineTest.class})
|
||||
@SuiteClasses({ExtractInterfaceTest.class, RenameTest.class, SelectTest.class, CleanupTest.class, FindReferencesTest.class, InlineTest.class, NoErrorsTest.class})
|
||||
public class EclipseTests {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package lombok.eclipse.compile;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.ICompilationUnit;
|
||||
import org.eclipse.jdt.core.IProblemRequestor;
|
||||
import org.eclipse.jdt.core.WorkingCopyOwner;
|
||||
import org.eclipse.jdt.core.compiler.IProblem;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import lombok.eclipse.EclipseRunner;
|
||||
import lombok.eclipse.SetupSingleFileTest;
|
||||
|
||||
@RunWith(EclipseRunner.class)
|
||||
public class NoErrorsTest {
|
||||
|
||||
@Rule
|
||||
public SetupSingleFileTest setup = new SetupSingleFileTest();
|
||||
|
||||
@Test
|
||||
public void fieldNameConstantsInAnnotation() throws Exception {
|
||||
ICompilationUnit cu = setup.getPackageFragment().getCompilationUnit("Usage.java");
|
||||
|
||||
final List<IProblem> problems = new ArrayList<IProblem>();
|
||||
final IProblemRequestor requestor = new IProblemRequestor() {
|
||||
@Override
|
||||
public void acceptProblem(IProblem problem) {
|
||||
problems.add(problem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginReporting() {
|
||||
problems.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endReporting() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
WorkingCopyOwner workingCopyOwner = new WorkingCopyOwner() {
|
||||
@Override
|
||||
public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) {
|
||||
return requestor;
|
||||
}
|
||||
};
|
||||
|
||||
ICompilationUnit workingCopy = cu.getWorkingCopy(workingCopyOwner, null);
|
||||
try {
|
||||
workingCopy.reconcile(ICompilationUnit.NO_AST, true, true, workingCopy.getOwner(), null);
|
||||
} finally {
|
||||
workingCopy.discardWorkingCopy();
|
||||
}
|
||||
|
||||
System.out.println(problems);
|
||||
assertTrue(problems.isEmpty());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user