PT #160962428: Create metadata for missing property quick fix

This commit is contained in:
BoykoAlex
2019-01-14 19:22:31 -05:00
parent 87cb45ae7d
commit 5b2b5e89af
23 changed files with 3073 additions and 5674 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2018 Pivotal, Inc.
* Copyright (c) 2016, 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -30,6 +30,7 @@ import java.util.function.Consumer;
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.ApplyWorkspaceEditResponse;
import org.eclipse.lsp4j.ClientCapabilities;
import org.eclipse.lsp4j.CodeLensOptions;
import org.eclipse.lsp4j.CompletionOptions;
import org.eclipse.lsp4j.Diagnostic;
@@ -78,7 +79,6 @@ import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.AsyncRunner;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.collect.ImmutableList;
@@ -139,6 +139,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
private Consumer<InitializeParams> initializeHandler;
private CompletableFuture<Void> initialized = new CompletableFuture<Void>();
private CompletableFuture<ClientCapabilities> clientCapabilities = new CompletableFuture<>();
private Runnable shutdownHandler;
@@ -214,7 +215,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
})
.toFuture();
}
Log.warn("Unknown command ignored: "+params.getCommand());
log.warn("Unknown command ignored: "+params.getCommand());
return CompletableFuture.completedFuture(false);
}
@@ -226,6 +227,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
@Override
public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
log.info("Initializing");
clientCapabilities.complete(params.getCapabilities());
// multi-root workspace handling
List<WorkspaceFolder> workspaceFolders = getWorkspaceFolders(params);
@@ -235,7 +237,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
else {
String rootUri = params.getRootUri();
if (rootUri==null) {
Log.debug("workspaceRoot NOT SET");
log.debug("workspaceRoot NOT SET");
} else {
List<WorkspaceFolder> singleRootFolder = new ArrayList<>();
String name;
@@ -255,9 +257,9 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
this.hasCompletionSnippetSupport = safeGet(false, () -> params.getCapabilities().getTextDocument().getCompletion().getCompletionItem().getSnippetSupport());
this.hasExecuteCommandSupport = safeGet(false, () -> params.getCapabilities().getWorkspace().getExecuteCommand()!=null);
this.hasFileWatcherRegistrationSupport = safeGet(false, () -> params.getCapabilities().getWorkspace().getDidChangeWatchedFiles().getDynamicRegistration());
Log.debug("workspaceRoots = "+getWorkspaceService().getWorkspaceRoots());
Log.debug("hasCompletionSnippetSupport = "+hasCompletionSnippetSupport);
Log.debug("hasExecuteCommandSupport = "+hasExecuteCommandSupport);
log.debug("workspaceRoots = "+getWorkspaceService().getWorkspaceRoots());
log.debug("hasCompletionSnippetSupport = "+hasCompletionSnippetSupport);
log.debug("hasExecuteCommandSupport = "+hasExecuteCommandSupport);
InitializeResult result = new InitializeResult();
@@ -348,7 +350,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
if (error instanceof ShowMessageException)
client.showMessage(((ShowMessageException) error).message);
else {
Log.log(message, error);
log.error(message, error);
MessageParams m = new MessageParams();
@@ -598,7 +600,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
diagnostics.add(d);
}
} catch (BadLocationException e) {
Log.warn("Invalid reconcile problem ignored", e);
log.warn("Invalid reconcile problem ignored", e);
}
}
};
@@ -606,7 +608,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
engine.reconcile(doc, problems);
})
.onErrorResume(error -> {
Log.log(error);
log.error("", error);
return Mono.empty();
})
.doFinally(ignore -> {
@@ -659,6 +661,10 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
return this;
}
public CompletableFuture<ClientCapabilities> getClientCapabilities() {
return clientCapabilities;
}
public synchronized void onInitialize(Consumer<InitializeParams> handler) {
Assert.isNull("Multiple initialize handlers not supported yet", this.initializeHandler);
this.initializeHandler = handler;

View File

@@ -27,11 +27,18 @@ public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexPr
private JavaProjectFinder javaProjectFinder;
private SpringPropertiesIndexManager indexManager;
private Runnable changeHandler = null;
private ProgressService progressService = (id, msg) -> { /*ignore*/ };
public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder, ProjectObserver projectObserver, FileObserver fileObserver, ValueProviderRegistry valueProviders) {
this.javaProjectFinder = javaProjectFinder;
this.indexManager = new SpringPropertiesIndexManager(valueProviders, projectObserver, fileObserver);
this.indexManager.addListener(info -> {
if (changeHandler != null) {
changeHandler.run();
}
});
}
@Override
@@ -47,4 +54,9 @@ public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexPr
this.progressService = progressService;
}
@Override
public void onChange(Runnable changeHandler) {
this.changeHandler = changeHandler;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015 Pivotal, Inc.
* Copyright (c) 2015, 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -26,8 +26,9 @@ import org.springframework.ide.eclipse.org.json.JSONObject;
* @author Alex Boyko
*/
public class MetadataManipulator {
private abstract class Content {
@Override
public abstract String toString();
public abstract void addProperty(JSONObject jsonObject) throws Exception;
}
@@ -43,6 +44,7 @@ public class MetadataManipulator {
this.object = o;
}
@Override
public String toString() {
return object.toString(indentFactor);
}
@@ -149,7 +151,7 @@ public class MetadataManipulator {
private ContentStore contentStore;
private Content fContent;
private int indentFactor = 2;
public MetadataManipulator(ContentStore contentStore) {
this.contentStore = contentStore;
}
@@ -166,7 +168,7 @@ public class MetadataManipulator {
public void setContents(String content) throws Exception {
Files.write(Paths.get(file.toURI()), content.getBytes(ENCODING));
}
});
}
@@ -227,4 +229,8 @@ public class MetadataManipulator {
return getContent() instanceof ParsedContent;
}
public String getTextContent() throws Exception {
return getContent().toString();
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2015 Pivotal, Inc.
* Copyright (c) 2015, 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,8 +13,7 @@ package org.springframework.ide.vscode.boot.metadata;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@FunctionalInterface
public interface SpringPropertyIndexProvider {
FuzzyMap<PropertyInfo> getIndex(IDocument doc);
void onChange(Runnable runnable);
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014 Pivotal, Inc.
* Copyright (c) 2014, 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.metadata.util;
/**
* @author Kris De Volder
*/
@FunctionalInterface
public interface Listener<T> {
void changed(T info);

View File

@@ -20,6 +20,7 @@ import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.boot.properties.completions.SpringPropertiesCompletionEngine;
import org.springframework.ide.vscode.boot.properties.hover.PropertiesHoverInfoProvider;
import org.springframework.ide.vscode.boot.properties.quickfix.AppPropertiesQuickFixes;
import org.springframework.ide.vscode.boot.properties.quickfix.CommonQuickfixes;
import org.springframework.ide.vscode.boot.properties.reconcile.SpringPropertiesReconcileEngine;
import org.springframework.ide.vscode.boot.yaml.quickfix.AppYamlQuickfixes;
import org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlReconcileEngine;
@@ -96,11 +97,25 @@ public class BootPropertiesLanguageServerComponents implements LanguageServerCom
this.projectObserver = serverParams.projectObserver;
this.yamlStructureProvider = yamlStructureProvider;
this.yamlAssistContextProvider = yamlAssistContextProvider;
this.propertiesReconciler = new SpringPropertiesReconcileEngine(indexProvider,
typeUtilProvider, new AppPropertiesQuickFixes(server.getQuickfixRegistry()));
this.ymlReconciler = new ApplicationYamlReconcileEngine(parser, indexProvider, typeUtilProvider,
new AppYamlQuickfixes(server.getQuickfixRegistry(), server.getTextDocumentService(),
yamlStructureProvider));
server.getClientCapabilities().thenAccept(clientCapabilities -> {
CommonQuickfixes commonQuickfixes = new CommonQuickfixes(server.getQuickfixRegistry(), javaProjectFinder,
clientCapabilities);
this.propertiesReconciler = new SpringPropertiesReconcileEngine(indexProvider,
typeUtilProvider, new AppPropertiesQuickFixes(server.getQuickfixRegistry(), commonQuickfixes));
this.ymlReconciler = new ApplicationYamlReconcileEngine(parser, indexProvider, typeUtilProvider,
new AppYamlQuickfixes(server.getQuickfixRegistry(), server.getTextDocumentService(),
yamlStructureProvider, commonQuickfixes));
});
indexProvider.onChange(() -> {
getReconcileEngine().ifPresent(reconciler -> {
server.getTextDocumentService().getAll().stream().filter(doc -> getInterestingLanguages().contains(doc.getLanguageId())).forEach(doc -> {
server.validateWith(doc.getId(), reconciler);
});
});
});
}
@Override

View File

@@ -41,10 +41,12 @@ public class AppPropertiesQuickFixes {
);
public final QuickfixType DEPRECATED_PROPERTY;
public final QuickfixType MISSING_PROPERTY;
private final Gson gson = new Gson();
public AppPropertiesQuickFixes(QuickfixRegistry r) {
public AppPropertiesQuickFixes(QuickfixRegistry r, CommonQuickfixes commonFixes) {
MISSING_PROPERTY = commonFixes.MISSING_PROPERTY;
DEPRECATED_PROPERTY = r.register("DEPRECATED_PROPERTY", (Object _params) -> {
DeprecatedPropertyData params = gson.fromJson((JsonElement)_params, DeprecatedPropertyData.class);
try {

View File

@@ -0,0 +1,146 @@
/*******************************************************************************
* Copyright (c) 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.properties.quickfix;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.lsp4j.ClientCapabilities;
import org.eclipse.lsp4j.CreateFile;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.ResourceOperationKind;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.metadata.MetadataManipulator;
import org.springframework.ide.vscode.boot.metadata.MetadataManipulator.ContentStore;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixRegistry;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixType;
import org.springframework.ide.vscode.commons.util.IOUtil;
import org.springframework.ide.vscode.commons.util.text.Region;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
/**
* Common quick fixes for YAML and properties
*
* @author Alex Boyko
*
*/
public class CommonQuickfixes {
public static final String MISSING_PROPERTY_APP_QF_ID = "MISSING_PROPERTY_APP";
private static final Logger log = LoggerFactory.getLogger(CommonQuickfixes.class);
private static final Path METADATA_PATH = Paths.get("META-INF", "additional-spring-configuration-metadata.json");
private static final QuickfixEdit NULL_FIX = new QuickfixEdit(
new WorkspaceEdit(ImmutableMap.of()),
null
);
public final QuickfixType MISSING_PROPERTY;
private final Gson gson = new Gson();
private static class SimpleContentStore implements ContentStore {
private String content;
SimpleContentStore(String content) {
this.content = content;
}
@Override
public String getContents() throws Exception {
return content;
}
@Override
public void setContents(String content) throws Exception {
this.content = content;
}
}
public CommonQuickfixes(QuickfixRegistry r, JavaProjectFinder projectFinder, ClientCapabilities clientCapabilities) {
if (clientCapabilities == null) {
throw new IllegalStateException("Client Capabilities have not been received!");
}
if (clientCapabilities.getWorkspace().getWorkspaceEdit() != null && clientCapabilities.getWorkspace().getWorkspaceEdit().getResourceOperations() != null && clientCapabilities.getWorkspace().getWorkspaceEdit().getResourceOperations().contains(ResourceOperationKind.Create)
&& Boolean.TRUE.equals(clientCapabilities.getWorkspace().getWorkspaceEdit().getDocumentChanges())) {
MISSING_PROPERTY = r.register(MISSING_PROPERTY_APP_QF_ID, (Object _params) -> {
MissingPropertyData params = gson.fromJson((JsonElement)_params, MissingPropertyData.class);
try {
Optional<IJavaProject> p = projectFinder.find(params.getDoc());
if (p.isPresent()) {
IJavaProject project = p.get();
List<File> sourceFolders = IClasspathUtil.getSourceFolders(project.getClasspath()).collect(Collectors.toList());
if (!sourceFolders.isEmpty()) {
WorkspaceEdit we = new WorkspaceEdit(new ArrayList<Either<TextDocumentEdit, ResourceOperation>>());
Path metadataFilePath = sourceFolders.stream().map(f -> f.toPath()).filter(path -> Files.exists(path.resolve(METADATA_PATH))).findFirst().orElse(null);
if (metadataFilePath == null) {
metadataFilePath = sourceFolders.get(0).toPath().resolve(METADATA_PATH);
we.getDocumentChanges().add(Either.forRight(new CreateFile(metadataFilePath.toUri().toString())));
}
if (metadataFilePath != null) {
String content = Files.exists(metadataFilePath) ? IOUtil.toString(Files.newInputStream(metadataFilePath)) : "";
MetadataManipulator metadata = new MetadataManipulator(new SimpleContentStore(content));
if (!metadata.isReliable()) {
log.error("Failed to add metadata!",
"'" + metadataFilePath + "' does not appear to contain valid JSON!\n");
} else {
metadata.addDefaultInfo(params.getProperty());
TextDocumentEdit edit = new TextDocumentEdit();
edit.setTextDocument(new VersionedTextDocumentIdentifier(metadataFilePath.toUri().toString(), null));
TextEdit textEdit = new TextEdit();
textEdit.setNewText(metadata.getTextContent());
TextDocument doc = new TextDocument(metadataFilePath.toUri().toString(), null);
doc.setText(content);
textEdit.setRange(doc.toRange(new Region(0, content.length())));
edit.setEdits(ImmutableList.of(textEdit));
we.getDocumentChanges().add(Either.forLeft(edit));
}
}
return new QuickfixEdit(we, null);
}
}
} catch (Exception e) {
log.error("", e);
}
return NULL_FIX;
});
} else {
MISSING_PROPERTY = null;
}
}
}

View File

@@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (c) 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.properties.quickfix;
import org.eclipse.lsp4j.TextDocumentIdentifier;
/**
* Missing Property Quickfix data
*
* @author Alex Boyko
*
*/
public class MissingPropertyData {
private TextDocumentIdentifier doc;
private String property;
public MissingPropertyData(TextDocumentIdentifier doc, String property) {
super();
this.setDoc(doc);
this.setProperty(property);
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public TextDocumentIdentifier getDoc() {
return doc;
}
public void setDoc(TextDocumentIdentifier doc) {
this.doc = doc;
}
}

View File

@@ -18,6 +18,7 @@ import static org.springframework.ide.vscode.commons.util.StringUtil.commonPrefi
import java.util.regex.Pattern;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
@@ -28,7 +29,9 @@ import org.springframework.ide.vscode.boot.metadata.types.TypeParser;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.boot.properties.quickfix.DeprecatedPropertyData;
import org.springframework.ide.vscode.boot.properties.quickfix.MissingPropertyData;
import org.springframework.ide.vscode.boot.properties.quickfix.AppPropertiesQuickFixes;
import org.springframework.ide.vscode.boot.properties.quickfix.CommonQuickfixes;
import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix.QuickfixData;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixType;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
@@ -113,7 +116,7 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
// it all with just passing around 'fullName' DocumentRegion. This may require changes
// in PropertyNavigator (probably these changes are also for the better making it simpler as well)
if (validProperty.isDeprecated()) {
problemCollector.accept(problemDeprecated(doc, propertyNameRegion, validProperty, quickFixes.DEPRECATED_PROPERTY));
problemCollector.accept(problemDeprecated(propertyNameRegion, validProperty, quickFixes.DEPRECATED_PROPERTY));
}
int offset = validProperty.getId().length() + propertyNameRegion.getStart();
PropertyNavigator navigator = new PropertyNavigator(doc, problemCollector, typeUtilProvider.getTypeUtil(doc), propertyNameRegion);
@@ -125,7 +128,7 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
//The name is invalid, with no 'prefix' of the name being a valid property name.
PropertyInfo similarEntry = index.findLongestCommonPrefixEntry(propertyNameRegion.toString());
CharSequence validPrefix = commonPrefix(similarEntry.getId(), keyName);
problemCollector.accept(problemUnkownProperty(propertyNameRegion, similarEntry, validPrefix));
problemCollector.accept(problemUnkownProperty(propertyNameRegion, similarEntry, validPrefix, quickFixes.MISSING_PROPERTY));
} //end: validProperty==null
} catch (Exception e) {
log.error("", e);
@@ -138,7 +141,7 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
}
}
protected SpringPropertyProblem problemDeprecated(IDocument doc, DocumentRegion region, PropertyInfo property, QuickfixType fixType) {
protected SpringPropertyProblem problemDeprecated(DocumentRegion region, PropertyInfo property, QuickfixType fixType) {
SpringPropertyProblem p = problem(PROP_DEPRECATED,
TypeUtil.deprecatedPropertyMessage(
property.getId(), null,
@@ -151,6 +154,7 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
p.setMetadata(property);
try {
IDocument doc = region.getDocument();
p.addQuickfix(new QuickfixData<>(fixType,
new DeprecatedPropertyData(doc.getUri(), doc.toRange(region), property.getDeprecationReplacement()),
"Replace with `" + property.getDeprecationReplacement() + "`"));
@@ -162,13 +166,26 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
}
protected SpringPropertyProblem problemUnkownProperty(DocumentRegion fullNameRegion,
PropertyInfo similarEntry, CharSequence validPrefix) {
PropertyInfo similarEntry, CharSequence validPrefix, QuickfixType... fixTypes) {
String fullName = fullNameRegion.toString();
SpringPropertyProblem p = problem(PROP_UNKNOWN_PROPERTY,
"'"+fullName+"' is an unknown property."+suggestSimilar(similarEntry, validPrefix, fullName),
fullNameRegion.subSequence(validPrefix.length())
);
p.setPropertyName(fullName);
IDocument doc = fullNameRegion.getDocument();
for (QuickfixType fixType : fixTypes) {
if (fixType != null) {
switch (fixType.getId()) {
case CommonQuickfixes.MISSING_PROPERTY_APP_QF_ID:
p.addQuickfix(new QuickfixData<>(fixType,
new MissingPropertyData(new TextDocumentIdentifier(doc.getUri()), fullName),
"Create metadata for `" + fullName +"`"));
break;
}
}
}
return p;
}

View File

@@ -14,6 +14,7 @@ import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.properties.quickfix.CommonQuickfixes;
import org.springframework.ide.vscode.boot.properties.quickfix.DeprecatedPropertyData;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit.CursorMovement;
@@ -48,6 +49,7 @@ public class AppYamlQuickfixes {
private static final Logger log = LoggerFactory.getLogger(AppYamlQuickfixes.class);
public final QuickfixType DEPRECATED_PROPERTY;
public final QuickfixType MISSING_PROPERTY;
private static final QuickfixEdit NULL_FIX = new QuickfixEdit(
new WorkspaceEdit(ImmutableMap.of()),
@@ -56,7 +58,8 @@ public class AppYamlQuickfixes {
private final Gson gson = new Gson();
public AppYamlQuickfixes(QuickfixRegistry r, SimpleTextDocumentService textDocumentService, YamlStructureProvider structureProvider) {
public AppYamlQuickfixes(QuickfixRegistry r, SimpleTextDocumentService textDocumentService, YamlStructureProvider structureProvider, CommonQuickfixes commonQuickfixes) {
MISSING_PROPERTY = commonQuickfixes.MISSING_PROPERTY;
DEPRECATED_PROPERTY = r.register("DEPRECATED_YAML_PROPERTY", (Object _params) -> {
DeprecatedPropertyData params = gson.fromJson((JsonElement)_params, DeprecatedPropertyData.class);
try {

View File

@@ -24,6 +24,7 @@ import java.util.regex.Pattern;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.boot.metadata.IndexNavigator;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
import org.springframework.ide.vscode.boot.metadata.types.Type;
@@ -32,7 +33,9 @@ import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil.BeanPropertyNameMode;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil.EnumCaseMode;
import org.springframework.ide.vscode.boot.metadata.types.TypedProperty;
import org.springframework.ide.vscode.boot.properties.quickfix.CommonQuickfixes;
import org.springframework.ide.vscode.boot.properties.quickfix.DeprecatedPropertyData;
import org.springframework.ide.vscode.boot.properties.quickfix.MissingPropertyData;
import org.springframework.ide.vscode.boot.yaml.quickfix.AppYamlQuickfixes;
import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix.QuickfixData;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixType;
@@ -174,7 +177,7 @@ public class ApplicationYamlASTReconciler implements YamlASTReconciler {
} else {
//both are null, this means there's no valid property with the current prefix
//whether exact or extending it with further navigation
unkownProperty(keyNode, subNav.getPrefix(), entry);
unkownProperty(root.getDocument().getUri(), keyNode, subNav.getPrefix(), entry, quickFixes.MISSING_PROPERTY);
}
}
}
@@ -320,9 +323,22 @@ public class ApplicationYamlASTReconciler implements YamlASTReconciler {
problems.accept(problem(ApplicationYamlProblemType.YAML_VALUE_TYPE_MISMATCH, e.getHighlightRegion(containingRegion), ExceptionUtil.getMessage(e)));
}
private void unkownProperty(Node node, String name, NodeTuple entry) {
private void unkownProperty(String docUri, Node node, String name, NodeTuple entry, QuickfixType... fixTypes) {
SpringPropertyProblem p = problem(ApplicationYamlProblemType.YAML_UNKNOWN_PROPERTY, node, "Unknown property '"+name+"'");
p.setPropertyName(extendForQuickfix(StringUtil.camelCaseToHyphens(name), entry.getValueNode()));
for (QuickfixType fixType : fixTypes) {
if (fixType != null) {
switch (fixType.getId()) {
case CommonQuickfixes.MISSING_PROPERTY_APP_QF_ID:
p.addQuickfix(new QuickfixData<>(fixType,
new MissingPropertyData(new TextDocumentIdentifier(docUri), name),
"Create metadata for `" + name +"`"));
break;
}
}
}
problems.accept(p);
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -53,6 +53,11 @@ public class PropertyIndexHarness {
return index;
}
}
@Override
public void onChange(Runnable runnable) {
}
};
public PropertyIndexHarness(ValueProviderRegistry valueProviders) {

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
"author": "Kris De Volder <kdevolder@pivotal.io>",
"engines": {
"npm": "^3.0.0",
"vscode": "^1.26.0"
"vscode": "^1.30.0"
},
"keywords": [],
"files": [
@@ -32,6 +32,6 @@
"typescript": "2.6.1",
"@types/node": "^7.0.43",
"vscode": "^1.1.22",
"vscode-languageclient": "4.1.3"
"vscode-languageclient": "5.2.1"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
"license": "EPL-1.0",
"engines": {
"npm": "^3.0.0",
"vscode": "^1.26.0"
"vscode": "^1.30.0"
},
"categories": [
"Programming Languages",
@@ -114,7 +114,7 @@
},
"dependencies": {
"@pivotal-tools/commons-vscode": "file:../commons-vscode/pivotal-tools-commons-vscode-0.2.2.tgz",
"vscode-languageclient": "4.1.3"
"vscode-languageclient": "5.2.1"
},
"devDependencies": {
"vsce": "^1.36.1",

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
"license": "EPL-1.0",
"engines": {
"npm": "^3.0.0",
"vscode": "^1.26.0"
"vscode": "^1.30.0"
},
"categories": [
"Programming Languages",
@@ -98,7 +98,7 @@
},
"dependencies": {
"@pivotal-tools/commons-vscode": "file:../commons-vscode/pivotal-tools-commons-vscode-0.2.2.tgz",
"vscode-languageclient": "4.1.3"
"vscode-languageclient": "5.2.1"
},
"devDependencies": {
"vsce": "^1.36.1",

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
"license": "EPL-1.0",
"engines": {
"npm": "^3.0.0",
"vscode": "^1.26.0"
"vscode": "^1.30.0"
},
"categories": [
"Programming Languages",
@@ -78,7 +78,7 @@
},
"dependencies": {
"@pivotal-tools/commons-vscode": "file:../commons-vscode/pivotal-tools-commons-vscode-0.2.2.tgz",
"vscode-languageclient": "4.1.3"
"vscode-languageclient": "5.2.1"
},
"devDependencies": {
"vsce": "^1.36.1",

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
"license": "EPL-1.0",
"engines": {
"npm": "^3.0.0",
"vscode": "^1.26.0"
"vscode": "^1.30.0"
},
"categories": [
"Programming Languages",
@@ -137,7 +137,7 @@
"dependencies": {
"@pivotal-tools/commons-vscode": "file:../commons-vscode/pivotal-tools-commons-vscode-0.2.2.tgz",
"@pivotal-tools/pipeline-builder": "^0.0.5",
"vscode-languageclient": "4.1.3"
"vscode-languageclient": "5.2.1"
},
"devDependencies": {
"vsce": "^1.36.1",