CodeActions to JDT reconciler. Don't use OR CU cache.

This commit is contained in:
aboyko
2023-08-18 14:57:48 -04:00
parent 8666ef9785
commit 4124efce85
15 changed files with 97 additions and 98 deletions

View File

@@ -31,9 +31,9 @@ public class Constants {
public static final String PREF_CHANGE_DETECTION = "boot-java.change-detection.on";
public static final String PREF_REWRITE_RECONCILE = "boot-java.rewrite.reconcile";
public static final String PREF_JAVA_RECONCILE = "boot-java.java.reconcile";
public static final String PREF_REWRITE_RECONCILE_PROMPT = "rewrite.reconcile-prompt";
public static final String PREF_JAVA_RECONCILE_PROMPT = "java.reconcile-prompt";
public static final String PREF_REWRITE_RECIPE_FILTERS = "boot-java.rewrite.recipe-filters";

View File

@@ -179,7 +179,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
IPreferenceStore preferenceStore = BootLanguageServerPlugin.getDefault().getPreferenceStore();
if (preferenceStore.getBoolean(Constants.PREF_REWRITE_RECONCILE_PROMPT) && !preferenceStore.getBoolean(Constants.PREF_REWRITE_RECONCILE)) {
if (preferenceStore.getBoolean(Constants.PREF_JAVA_RECONCILE_PROMPT) && !preferenceStore.getBoolean(Constants.PREF_JAVA_RECONCILE)) {
PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
try {
NotificationQuestionWithLink question = new NotificationQuestionWithLink(
@@ -187,9 +187,9 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
"Do you wish to enable additional Java sources reconciling to get Spring specific validations and suggestions?\n\n" +
"See <a>Validations And Quick Fixes</a> for more details.",
new URL("https://github.com/spring-projects/sts4/wiki/Validations-And-Quick-Fixes"),
() -> preferenceStore.setValue(Constants.PREF_REWRITE_RECONCILE, true),
() -> preferenceStore.setValue(Constants.PREF_JAVA_RECONCILE, true),
() -> {},
() -> preferenceStore.setValue(Constants.PREF_REWRITE_RECONCILE_PROMPT, false));
() -> preferenceStore.setValue(Constants.PREF_JAVA_RECONCILE_PROMPT, false));
question.setDelayClose(-1);
question.open();
} catch (Exception e) {
@@ -212,6 +212,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
Map<String, Object> scanTestJavaSources = new HashMap<>();
Map<String, Object> validation = new HashMap<>();
Map<String, Object> validationSpelExpressions = new HashMap<>();
Map<String, Object> javaValidation = new HashMap<>();
IPreferenceStore preferenceStore = BootLanguageServerPlugin.getDefault().getPreferenceStore();
@@ -227,8 +228,10 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
bootChangeDetection.put("on", preferenceStore.getBoolean(Constants.PREF_CHANGE_DETECTION));
scanTestJavaSources.put("on", preferenceStore.getBoolean(Constants.PREF_SCAN_JAVA_TEST_SOURCES));
javaValidation.put("reconcilers", preferenceStore.getBoolean(Constants.PREF_JAVA_RECONCILE));
validationSpelExpressions.put("on", preferenceStore.getBoolean(Constants.PREF_VALIDATION_SPEL_EXPRESSIONS));
validation.put("spel", validationSpelExpressions);
validation.put("java", javaValidation);
bootJavaObj.put("live-information", liveInformation);
bootJavaObj.put("support-spring-xml-config", supportXML);
@@ -239,7 +242,6 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
bootJavaObj.put("remote-apps", getAllRemoteApps());
bootJavaObj.put("rewrite", Map.of(
"reconcile", preferenceStore.getBoolean(Constants.PREF_REWRITE_RECONCILE),
"recipe-filters", StringListEditor.decode(preferenceStore.getString(Constants.PREF_REWRITE_RECIPE_FILTERS)),
"scan-directories", FileListEditor.getValuesFromPreference(preferenceStore.getString(Constants.PREF_REWRITE_RECIPES_SCAN_DIRS)),
"scan-files", FileListEditor.getValuesFromPreference(preferenceStore.getString(Constants.PREF_REWRITE_RECIPES_SCAN_FILES))
@@ -342,7 +344,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
this.noHandler = noHandler;
this.stopAskingHandler = stopAskingHandler;
setParentShell(PlatformUI.getWorkbench().getDisplay().getActiveShell());
setParentShell(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
setBlockOnOpen(true);
}

View File

@@ -30,11 +30,6 @@ public class RewritePreferencePage extends FieldEditorPreferencePage implements
addField(new BooleanFieldEditor(Constants.PREF_REWRITE_PROJECT_REFACTORINGS,
"Project refactoring actions", fieldEditorParent));
addField(new BooleanFieldEditor(Constants.PREF_REWRITE_RECONCILE,
"Reconciling of Java Sources", fieldEditorParent));
addField(new BooleanFieldEditor(Constants.PREF_REWRITE_RECONCILE_PROMPT,
"Prompt for Reconciling of Java Sources", fieldEditorParent));
}

View File

@@ -45,8 +45,8 @@ public class PrefsInitializer extends AbstractPreferenceInitializer {
preferenceStore.setDefault(Constants.PREF_SCAN_JAVA_TEST_SOURCES, false);
preferenceStore.setDefault(Constants.PREF_REWRITE_RECONCILE_PROMPT, true);
preferenceStore.setDefault(Constants.PREF_REWRITE_RECONCILE, false);
preferenceStore.setDefault(Constants.PREF_JAVA_RECONCILE_PROMPT, true);
preferenceStore.setDefault(Constants.PREF_JAVA_RECONCILE, false);
preferenceStore.setDefault(Constants.PREF_REWRITE_PROJECT_REFACTORINGS, true);
preferenceStore.setDefault(Constants.PREF_REWRITE_RECIPE_FILTERS, StringListEditor.encode(new String[] {

View File

@@ -10,40 +10,30 @@
*******************************************************************************/
package org.springframework.tooling.boot.ls.prefs;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.springframework.tooling.boot.ls.BootLanguageServerPlugin;
import org.springframework.tooling.boot.ls.Constants;
public class ValidationPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
public ValidationPreferencePage() {
}
public ValidationPreferencePage(String title) {
super(title);
}
public ValidationPreferencePage(String title, ImageDescriptor image) {
super(title, image);
}
public class ValidationPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
@Override
public void init(IWorkbench workbench) {
setPreferenceStore(BootLanguageServerPlugin.getDefault().getPreferenceStore());
}
@Override
protected Control createContents(Composite parent) {
return null;
}
@Override
public void createControl(Composite parent) {
Composite content = new Composite(parent, SWT.NONE);
setControl(content);
protected void createFieldEditors() {
Composite fieldEditorParent = getFieldEditorParent();
addField(new BooleanFieldEditor(Constants.PREF_JAVA_RECONCILE,
"Reconciling of Java Sources", fieldEditorParent));
addField(new BooleanFieldEditor(Constants.PREF_JAVA_RECONCILE_PROMPT,
"Prompt for Reconciling of Java Sources", fieldEditorParent));
}
}

View File

@@ -154,8 +154,8 @@ public class BootJavaConfig implements InitializingBean {
return enabled != null && enabled.booleanValue();
}
public boolean isRewriteReconcileEnabled() {
Boolean enabled = getRawSettings().getBoolean("boot-java", "rewrite", "reconcile");
public boolean isJavaSourceReconcileEnabled() {
Boolean enabled = getRawSettings().getBoolean("boot-java", "validation", "java", "reconcilers");
return enabled == null ? false : enabled.booleanValue();
}

View File

@@ -38,8 +38,8 @@ public class RewriteConfig {
}
@ConditionalOnBean(RewriteRecipeRepository.class)
@Bean RewriteRefactorings rewriteRefactorings(SimpleLanguageServer server, JavaProjectFinder projectFinder, RewriteRecipeRepository recipeRepo, RewriteCompilationUnitCache cuCache) {
return new RewriteRefactorings(server, projectFinder, recipeRepo, cuCache);
@Bean RewriteRefactorings rewriteRefactorings(SimpleLanguageServer server, JavaProjectFinder projectFinder, RewriteRecipeRepository recipeRepo) {
return new RewriteRefactorings(server, projectFinder, recipeRepo);
}
@ConditionalOnBean(RewriteRecipeRepository.class)

View File

@@ -58,6 +58,10 @@ public class JdtReconciler implements JavaReconciler {
@Override
public void reconcile(IJavaProject project, final IDocument doc, final IProblemCollector problemCollector) {
if (!config.isJavaSourceReconcileEnabled()) {
return;
}
final long s = System.currentTimeMillis();
URI uri = URI.create(doc.getUri());
compilationUnitCache.withCompilationUnit(project, uri, cu -> {
@@ -75,6 +79,9 @@ public class JdtReconciler implements JavaReconciler {
public void reconcile(IJavaProject project, URI docUri, CompilationUnit cu, IProblemCollector problemCollector, boolean isCompleteAst) throws RequiredCompleteAstException {
if (!config.isJavaSourceReconcileEnabled()) {
return;
}
for (JdtAstReconciler reconciler : getApplicableReconcilers(project)) {
try {
reconciler.reconcile(project, docUri, cu, problemCollector, isCompleteAst);

View File

@@ -92,7 +92,8 @@ public class RewriteCodeActionHandler implements JavaCodeActionHandler {
@Override
public List<Either<Command, CodeAction>> handle(IJavaProject project, CancelChecker cancelToken,
CodeActionCapabilities capabilities, CodeActionContext context, TextDocument doc, IRegion region) {
if (!config.isRewriteReconcileEnabled()) {
// Short circuit here to avoid parsing the java source for nothing.
if (!config.isJavaSourceReconcileEnabled()) {
return Collections.emptyList();
}

View File

@@ -76,33 +76,33 @@ public class RewriteReconciler implements JavaReconciler {
@Override
public void reconcile(IJavaProject project, IDocument doc, IProblemCollector problemCollector) {
if (!config.isRewriteReconcileEnabled()) {
return;
}
long start = System.currentTimeMillis();
try {
problemCollector.beginCollecting();
List<RecipeCodeActionDescriptor> descriptors = getProblemRecipeDescriptors(project);
if (!descriptors.isEmpty()) {
CompilationUnit cu = cuCache.getCU(project, URI.create(doc.getUri()));
if (cu != null) {
collectProblems(project, descriptors, doc, cu, problemCollector::accept);
}
}
} catch (Exception e) {
if (ORAstUtils.isExceptionFromInterrupedThread(e)) {
log.debug("", e);
} else {
log.error("", e);
}
} finally {
problemCollector.endCollecting();
log.info("reconciling (OpenRewrite): " + doc.getUri() + " done in " + (System.currentTimeMillis() - start) + "ms");
}
// if (!config.isRewriteReconcileEnabled()) {
// return;
// }
//
// long start = System.currentTimeMillis();
//
// try {
// problemCollector.beginCollecting();
//
// List<RecipeCodeActionDescriptor> descriptors = getProblemRecipeDescriptors(project);
//
// if (!descriptors.isEmpty()) {
// CompilationUnit cu = cuCache.getCU(project, URI.create(doc.getUri()));
// if (cu != null) {
// collectProblems(project, descriptors, doc, cu, problemCollector::accept);
// }
// }
// } catch (Exception e) {
// if (ORAstUtils.isExceptionFromInterrupedThread(e)) {
// log.debug("", e);
// } else {
// log.error("", e);
// }
// } finally {
// problemCollector.endCollecting();
// log.info("reconciling (OpenRewrite): " + doc.getUri() + " done in " + (System.currentTimeMillis() - start) + "ms");
// }
}
private List<ReconcileProblem> createProblems(IDocument doc, FixAssistMarker m, J astNode) {
@@ -140,7 +140,7 @@ public class RewriteReconciler implements JavaReconciler {
@Override
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs, Runnable incrementProgress) {
if (!config.isRewriteReconcileEnabled()) {
if (!config.isJavaSourceReconcileEnabled()) {
return Collections.emptyMap();
}
@@ -251,7 +251,7 @@ public class RewriteReconciler implements JavaReconciler {
// Parse in batches and share the parser
private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs, JavaParser javaParser, JavaSourceSet javaSourceSet, Runnable incrementProgress) {
Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
if (javaParser != null && config.isRewriteReconcileEnabled()) {
if (javaParser != null && config.isJavaSourceReconcileEnabled()) {
try {
List<RecipeCodeActionDescriptor> descriptors = getProblemRecipeDescriptors(project);

View File

@@ -16,7 +16,6 @@ import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -70,17 +69,14 @@ public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler
private SimpleLanguageServer server;
private RewriteCompilationUnitCache cuCache;
private JavaProjectFinder projectFinder;
private Gson gson;
public RewriteRefactorings(SimpleLanguageServer server, JavaProjectFinder projectFinder, RewriteRecipeRepository recipeRepo, RewriteCompilationUnitCache cuCache) {
public RewriteRefactorings(SimpleLanguageServer server, JavaProjectFinder projectFinder, RewriteRecipeRepository recipeRepo) {
this.server = server;
this.projectFinder = projectFinder;
this.recipeRepo = recipeRepo;
this.cuCache = cuCache;
this.gson = new GsonBuilder()
.registerTypeAdapter(RecipeScope.class, (JsonDeserializer<RecipeScope>) (json, type, context) -> {
try {
@@ -164,13 +160,9 @@ public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler
progress.done();
}
} else {
if (data.getTypeStubs().length == 0) {
cus = data.getDocUris().stream().map(docUri -> cuCache.getCU(project.get(), URI.create(docUri))).filter(Objects::nonNull).collect(Collectors.toList());
} else {
JavaParser jp = ORAstUtils.createJavaParserBuilder(project.get()).dependsOn(data.getTypeStubs()).build();
List<Input> inputs = data.getDocUris().stream().map(URI::create).map(Paths::get).map(p -> ORAstUtils.getParserInput(server.getTextDocumentService(), p)).collect(Collectors.toList());
cus = ORAstUtils.parseInputs(jp, inputs, null);
}
JavaParser jp = ORAstUtils.createJavaParserBuilder(project.get()).dependsOn(data.getTypeStubs()).build();
List<Input> inputs = data.getDocUris().stream().map(URI::create).map(Paths::get).map(p -> ORAstUtils.getParserInput(server.getTextDocumentService(), p)).collect(Collectors.toList());
cus = ORAstUtils.parseInputs(jp, inputs, null);
return applyRecipe(r, project.get(), cus);
}
}

View File

@@ -61,6 +61,10 @@ public class SpringValidationBeanMethodNotPublicTest {
@BeforeEach
public void setup() throws Exception {
harness.intialize(null);
String changedSettings = "{\"boot-java\": {\"validation\": {\"java\": { \"reconcilers\": true}}}}";
JsonElement settingsAsJson = new Gson().fromJson(changedSettings, JsonElement.class);
harness.changeConfiguration(new Settings(settingsAsJson));
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-spring-validations/").toURI());
@@ -105,7 +109,7 @@ public class SpringValidationBeanMethodNotPublicTest {
assertEquals(1, diagnostics.size());
assertEquals(DiagnosticSeverity.Hint, diagnostic.getSeverity());
String changedSettings = "{\"spring-boot\": {\"ls\": {\"problem\": {\"boot2\": {\"JAVA_PUBLIC_BEAN_METHOD\": \"ERROR\"}}}}}";
String changedSettings = "{\"spring-boot\": {\"ls\": {\"problem\": {\"boot2\": {\"JAVA_PUBLIC_BEAN_METHOD\": \"ERROR\"}}}}, \"boot-java\": {\"validation\": {\"java\": { \"reconcilers\": true}}}}";
JsonElement settingsAsJson = new Gson().fromJson(changedSettings, JsonElement.class);
Settings settings = new Settings(settingsAsJson);

View File

@@ -56,6 +56,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFin
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
@@ -65,6 +66,9 @@ import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
/**
* @author Martin Lippert
*/
@@ -145,6 +149,10 @@ public class ValueSpelExpressionValidationTest {
public void setup() throws Exception {
harness.intialize(null);
String changedSettings = "{\"boot-java\": {\"validation\": {\"java\": { \"reconcilers\": true}}}}";
JsonElement settingsAsJson = new Gson().fromJson(changedSettings, JsonElement.class);
harness.changeConfiguration(new Settings(settingsAsJson));
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotations/").toURI());
docUri = directory.toPath().resolve("src/main/java/org/test/TestValueCompletion.java").toUri().toASCIIString();

View File

@@ -23,8 +23,8 @@ const FACTORIES_LANGUAGE_ID = "spring-factories";
const YES = 'Yes';
const NO = 'No';
const STOP_ASKING = "Stop Asking";
const RECONCILING_PREF_KEY = 'boot-java.rewrite.reconcile';
const RECONCILING_PROMPT_PREF_KEY = 'vscode-spring-boot.rewrite.reconcile-prompt';
const RECONCILING_PREF_KEY = 'boot-java.validation.java.reconcilers';
const RECONCILING_PROMPT_PREF_KEY = 'vscode-spring-boot.java.reconcile-prompt';
/** Called when extension is activated */
export function activate(context: VSCode.ExtensionContext): Thenable<ExtensionAPI> {

View File

@@ -139,6 +139,16 @@
"title": "Features",
"order": 100,
"properties": {
"boot-java.validation.java.reconcilers": {
"type": "boolean",
"default": false,
"description": "Reconciling Java Sources"
},
"vscode-spring-boot.java.reconcile-prompt": {
"type": "boolean",
"default": true,
"description": "Reconciling Java Sources Prompt enabled"
},
"boot-java.live-information.automatic-connection.on": {
"type": "boolean",
"default": true,
@@ -233,16 +243,6 @@
"default": true,
"description": "Recipes refactoring entire Maven project via commands"
},
"boot-java.rewrite.reconcile": {
"type": "boolean",
"default": false,
"description": "Reconciling Java Sources"
},
"vscode-spring-boot.rewrite.reconcile-prompt": {
"type": "boolean",
"default": true,
"description": "Reconciling Java Sources Prompt enabled"
},
"boot-java.rewrite.recipe-filters": {
"type": "array",
"default": [
@@ -1038,4 +1038,4 @@
"extensionDependencies": [
"redhat.java"
]
}
}