initial re-work of async behavior of language server, looking at the text document service first

This commit is contained in:
Martin Lippert
2021-02-06 08:49:05 +01:00
parent 6e0bb81cbe
commit 8238c1dc90
26 changed files with 463 additions and 450 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2020 Pivotal, Inc.
* Copyright (c) 2018, 2021 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
@@ -63,7 +63,7 @@ public class PropertiesJavaDefinitionHandler implements DefinitionHandler, Langu
@Override
public List<LocationLink> handle(DefinitionParams definitionParams) {
try {
TextDocument doc = documents.get(definitionParams);
TextDocument doc = documents.getLatestSnapshot(definitionParams);
TypeUtil typeUtil = params.typeUtilProvider.getTypeUtil(sourceLinks, doc);
FuzzyMap<PropertyInfo> index = params.indexProvider.getIndex(doc).getProperties();
int offset;

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2020 Pivotal, Inc.
* Copyright (c) 2019, 2021 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
@@ -99,7 +99,7 @@ public class XmlBeansConfigDefinitionHandler implements DefinitionHandler, Langu
JavaTypeHyperlinkProvider javaTypeHyperlinkProvider = new JavaTypeHyperlinkProvider(projectFinder, locationProvider);
PropertyNameHyperlinkProvider propertyNameHyperlinkProvider = new PropertyNameHyperlinkProvider(projectFinder, locationProvider);
BeanRefHyperlinkProvider beanRefHyperlinkProvider = new BeanRefHyperlinkProvider(projectFinder, symbolIndex, documents);
BeanRefHyperlinkProvider beanRefHyperlinkProvider = new BeanRefHyperlinkProvider(projectFinder, symbolIndex);
List<JavaTypeHyperlinkProvider> typeHandlersOnly = Arrays.asList(javaTypeHyperlinkProvider);
List<PropertyNameHyperlinkProvider> propertyNameHandlers = Arrays.asList(propertyNameHyperlinkProvider);
@@ -143,7 +143,7 @@ public class XmlBeansConfigDefinitionHandler implements DefinitionHandler, Langu
public List<LocationLink> handle(DefinitionParams params) {
try {
if (config.isSpringXMLSupportEnabled() && config.areXmlHyperlinksEnabled()) {
TextDocument doc = documents.get(params);
TextDocument doc = documents.getLatestSnapshot(params);
if (doc != null) {
String content = doc.get();

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2020 Pivotal, Inc.
* Copyright (c) 2018, 2021 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
@@ -70,7 +70,7 @@ public class YamlPropertiesJavaDefinitionHandler implements DefinitionHandler, L
@Override
public List<LocationLink> handle(DefinitionParams definitionParams) {
try {
TextDocument doc = documents.get(definitionParams);
TextDocument doc = documents.getLatestSnapshot(definitionParams);
int offset = doc.toOffset(definitionParams.getPosition());
YamlFileAST ast = getAst(doc);
if (ast != null) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2018 Pivotal, Inc.
* Copyright (c) 2017, 2021 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
@@ -40,8 +40,8 @@ public class BootJavaCodeLensEngine implements CodeLensHandler {
SimpleTextDocumentService documents = server.getTextDocumentService();
String docURI = params.getTextDocument().getUri();
if (documents.get(docURI) != null) {
TextDocument doc = documents.get(docURI).copy();
TextDocument doc = documents.getLatestSnapshot(docURI);
if (doc != null) {
// Spring Boot LS get events from boot properties files as well, so filter them out
if (server.getInterestingLanguages().contains(doc.getLanguageId())) {
try {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2020 Pivotal, Inc.
* Copyright (c) 2018, 2021 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
@@ -42,10 +42,9 @@ public class BootJavaDocumentHighlightEngine implements DocumentHighlightHandler
@Override
public List<DocumentHighlight> handle(DocumentHighlightParams params) {
SimpleTextDocumentService documents = server.getTextDocumentService();
String docURI = params.getTextDocument().getUri();
if (documents.get(docURI) != null) {
TextDocument doc = documents.get(docURI).copy();
TextDocument doc = documents.getLatestSnapshot(params);
if (doc != null) {
// Spring Boot LS get events from boot properties files as well, so filter them out
if (doc != null && server.getInterestingLanguages().contains(doc.getLanguageId())) {
try {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 Pivotal, Inc.
* Copyright (c) 2017, 2021 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
@@ -73,8 +73,9 @@ public class BootJavaHoverProvider implements HoverHandler {
@Override
public Hover handle(HoverParams params) {
SimpleTextDocumentService documents = server.getTextDocumentService();
if (documents.get(params) != null) {
TextDocument doc = documents.get(params).copy();
TextDocument doc = documents.getLatestSnapshot(params);
if (doc != null) {
// Spring Boot LS get events from boot properties files as well, so filter them out
if (server.getInterestingLanguages().contains(doc.getLanguageId())) {
try {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 Pivotal, Inc.
* Copyright (c) 2017, 2021 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,8 +53,9 @@ public class BootJavaReferencesHandler implements ReferencesHandler {
@Override
public List<? extends Location> handle(ReferenceParams params) {
SimpleTextDocumentService documents = server.getTextDocumentService();
TextDocument doc = documents.get(params).copy();
SimpleTextDocumentService documents = server.getTextDocumentService();
TextDocument doc = documents.getLatestSnapshot(params);
if (doc != null) {
// Spring Boot LS get events from boot properties files as well, so filter them out
if (server.getInterestingLanguages().contains(doc.getLanguageId())) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2019 Pivotal, Inc.
* Copyright (c) 2017, 2021 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
@@ -37,10 +37,10 @@ public class SpringProcessLiveHoverUpdater {
private final SimpleLanguageServer server;
private final BootJavaHoverProvider hoverProvider;
private final JavaProjectFinder projectFinder;
private boolean highlightsEnabled = true;
private JavaProjectFinder projectFinder;
private final Map<String, AtomicReference<IJavaProject>> watchedDocs;
private boolean highlightsEnabled = true;
public SpringProcessLiveHoverUpdater(
SimpleLanguageServer server,
@@ -56,11 +56,7 @@ public class SpringProcessLiveHoverUpdater {
server.getTextDocumentService().onDidChangeContent(params -> {
TextDocument doc = params.getDocument();
if (BootJavaLanguageServerComponents.LANGUAGES.contains(doc.getLanguageId())) {
try {
watchDocument(doc.getUri());
} catch (Throwable t) {
log.error("", t);
}
watchDocument(doc.getUri());
}
});
@@ -81,7 +77,14 @@ public class SpringProcessLiveHoverUpdater {
public void watchDocument(String docURI) {
this.watchedDocs.putIfAbsent(docURI, new AtomicReference<IJavaProject>());
updateDoc(docURI);
CompletableFuture.runAsync(() -> {
try {
updateDoc(docURI);
} catch (Throwable t) {
log.error("", t);
}
});
}
public void unwatchDocument(String docURI) {
@@ -89,6 +92,7 @@ public class SpringProcessLiveHoverUpdater {
cleanupLiveHints(docURI);
}
// runs async
private void updateDoc(String docURI) {
try {
IJavaProject project = getCachedProject(docURI);
@@ -99,6 +103,7 @@ public class SpringProcessLiveHoverUpdater {
}
}
// runs async
private void update() {
if (this.watchedDocs.size() > 0) {
try {
@@ -112,10 +117,11 @@ public class SpringProcessLiveHoverUpdater {
}
}
// runs async
private void update(String docURI, IJavaProject project) {
if (highlightsEnabled) {
try {
TextDocument doc = this.server.getTextDocumentService().get(docURI);
TextDocument doc = this.server.getTextDocumentService().getLatestSnapshot(docURI);
if (doc != null) {
CodeLens[] infos = this.hoverProvider.getLiveHoverHints(doc, project);
publishLiveHints(docURI, infos);
@@ -126,6 +132,7 @@ public class SpringProcessLiveHoverUpdater {
}
}
// runs async
private IJavaProject getCachedProject(String docURI) {
AtomicReference<IJavaProject> reference = this.watchedDocs.get(docURI);
if (reference != null) {
@@ -141,8 +148,9 @@ public class SpringProcessLiveHoverUpdater {
return null;
}
// runs async
private IJavaProject identifyProject(String docURI) {
TextDocument doc = this.server.getTextDocumentService().get(docURI);
TextDocument doc = this.server.getTextDocumentService().getLatestSnapshot(docURI);
if (doc != null) {
return projectFinder.find(doc.getId()).orElse(null);
}
@@ -151,8 +159,9 @@ public class SpringProcessLiveHoverUpdater {
}
}
// runs sync or async
private void publishLiveHints(String docURI, CodeLens[] codeLenses) {
TextDocument doc = server.getTextDocumentService().get(docURI);
TextDocument doc = server.getTextDocumentService().getLatestSnapshot(docURI);
if (doc != null) {
int version = doc.getVersion();
VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(docURI, version);
@@ -160,8 +169,9 @@ public class SpringProcessLiveHoverUpdater {
}
}
// runs sync or async
private void cleanupLiveHints(String docURI) {
publishLiveHints(docURI, new CodeLens[0]);
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 Pivotal, Inc.
* Copyright (c) 2017, 2021 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
@@ -18,9 +18,6 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import java.util.function.Function;
import java.util.stream.Stream;
@@ -45,13 +42,11 @@ 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.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.util.AsyncRunner;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import reactor.core.scheduler.Schedulers;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
@@ -62,95 +57,94 @@ public final class CompilationUnitCache implements DocumentContentProvider {
private static final long CU_ACCESS_EXPIRATION = 1;
private JavaProjectFinder projectFinder;
private ProjectObserver projectObserver;
private Cache<URI, CompilationUnit> uriToCu;
private Cache<IJavaProject, Set<URI>> projectToDocs;
private Cache<IJavaProject, Tuple2<List<Classpath>, INameEnvironmentWithProgress>> lookupEnvCache;
private ProjectObserver.Listener projectListener;
private SimpleTextDocumentService documents;
private AsyncRunner async;
private final ProjectObserver.Listener projectListener;
private final SimpleTextDocumentService documentService;
// private AsyncRunner async;
private ReadLock readLock;
private WriteLock writeLock;
private final Cache<URI, CompilationUnit> uriToCu;
private final Cache<IJavaProject, Set<URI>> projectToDocs;
private final Cache<IJavaProject, Tuple2<List<Classpath>, INameEnvironmentWithProgress>> lookupEnvCache;
// private ReadLock readLock;
// private WriteLock writeLock;
public CompilationUnitCache(JavaProjectFinder projectFinder, SimpleLanguageServer server, ProjectObserver projectObserver) {
this.projectFinder = projectFinder;
this.projectObserver = projectObserver;
this.lookupEnvCache = CacheBuilder.newBuilder().build();
// PT 154618835 - Avoid retaining the CU in the cache as it consumes memory if it hasn't been
// accessed after some time
uriToCu = CacheBuilder.newBuilder()
this.uriToCu = CacheBuilder.newBuilder()
.expireAfterWrite(CU_ACCESS_EXPIRATION, TimeUnit.MINUTES)
.build();
projectToDocs = CacheBuilder.newBuilder().build();
this.projectToDocs = CacheBuilder.newBuilder().build();
this.lookupEnvCache = CacheBuilder.newBuilder().build();
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
readLock = lock.readLock();
writeLock = lock.writeLock();
// ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
// this.readLock = lock.readLock();
// this.writeLock = lock.writeLock();
this.documents = server == null ? null : server.getTextDocumentService();
this.async = server == null ? new AsyncRunner(Schedulers.single()) : server.getAsync();
this.documentService = server == null ? null : server.getTextDocumentService();
// this.async = server == null ? new AsyncRunner(Schedulers.single()) : server.getAsync();
if (documents != null) {
documents.onDidChangeContent(doc -> invalidateCuForJavaFile(doc.getDocument().getId().getUri()));
documents.onDidClose(doc -> invalidateCuForJavaFile(doc.getId().getUri()));
// IMPORTANT ===> these notifications arrive within the lsp message loop, so reactions to them have to be fast
// and not be blocked by waiting for anything
if (documentService != null) {
documentService.onDidChangeContent(doc -> invalidateCuForJavaFile(doc.getDocument().getId().getUri()));
documentService.onDidClose(doc -> invalidateCuForJavaFile(doc.getId().getUri()));
}
for (IJavaProject project : projectFinder.all()) {
logger.info("CU Cache: initial lookup env creation for project <{}>", project.getElementName());
loadLookupEnvTuple(project);
}
async.execute(() -> {
writeLock.lock();
try {
for (IJavaProject project : projectFinder.all()) {
loadLookupEnvTuple(project);
}
} finally {
writeLock.unlock();
}
});
projectListener = new ProjectObserver.Listener() {
@Override
public void deleted(IJavaProject project) {
logger.info("CU Cache: deleted project {}", project.getElementName());
async.execute(() -> {
writeLock.lock();
try {
// async.execute(() -> {
// writeLock.lock();
// try {
invalidateProject(project);
} finally {
writeLock.unlock();
}
});
// } finally {
// writeLock.unlock();
// }
// });
}
@Override
public void created(IJavaProject project) {
logger.info("CU Cache: created project {}", project.getElementName());
async.execute(() -> {
writeLock.lock();
try {
// async.execute(() -> {
// writeLock.lock();
// try {
invalidateProject(project);
// Load the new cache the value right away
loadLookupEnvTuple(project);
} finally {
writeLock.unlock();
}
});
// } finally {
// writeLock.unlock();
// }
// });
}
@Override
public void changed(IJavaProject project) {
logger.info("CU Cache: changed project {}", project.getElementName());
async.execute(() -> {
writeLock.lock();
try {
// async.execute(() -> {
// writeLock.lock();
// try {
invalidateProject(project);
// Load the new cache the value right away
loadLookupEnvTuple(project);
} finally {
writeLock.unlock();
}
});
// } finally {
// writeLock.unlock();
// }
// });
}
};
@@ -182,9 +176,10 @@ public final class CompilationUnitCache implements DocumentContentProvider {
}
public <T> T withCompilationUnit(IJavaProject project, URI uri, Function<CompilationUnit, T> requestor) {
logger.info("CU Cache: work item for doc {}", uri.toString());
if (project != null) {
readLock.lock();
CompilationUnit cu = null;
try {
@@ -193,20 +188,23 @@ public final class CompilationUnitCache implements DocumentContentProvider {
String utiStr = uri.toString();
String unitName = utiStr.substring(utiStr.lastIndexOf("/"));
CompilationUnit cUnit = parse2(fetchContent(uri).toCharArray(), utiStr, unitName, lookupEnvTuple.getT1(), lookupEnvTuple.getT2());
projectToDocs.get(project, () -> new HashSet<>()).add(uri);
logger.info("CU Cache: created new AST for {}", uri.toString());
return cUnit;
});
if (cu != null) {
projectToDocs.get(project, () -> new HashSet<>()).add(uri);
}
} catch (Exception e) {
logger.error("", e);
} finally {
readLock.unlock();
}
if (cu != null) {
try {
logger.info("CU Cache: sync start on AST for {}", uri.toString());
synchronized (cu.getAST()) {
return requestor.apply(cu);
}
@@ -214,6 +212,9 @@ public final class CompilationUnitCache implements DocumentContentProvider {
catch (Exception e) {
logger.error("", e);
}
finally {
logger.info("CU Cache: sync end on AST for {}", uri.toString());
}
}
}
@@ -221,51 +222,6 @@ public final class CompilationUnitCache implements DocumentContentProvider {
}
private void invalidateCuForJavaFile(String uriStr) {
URI uri = URI.create(uriStr);
writeLock.lock();
try {
uriToCu.invalidate(uri);
} finally {
writeLock.unlock();
}
}
// public static CompilationUnit parse(TextDocument document, IJavaProject project) throws Exception {
// String[] classpathEntries = getClasspathEntries(project);
// String docURI = document.getUri();
// String unitName = docURI.substring(docURI.lastIndexOf("/"));
// char[] source = document.get(0, document.getLength()).toCharArray();
// return parse(source, docURI, unitName, classpathEntries);
// }
//
// public CompilationUnit parse(String uri, char[] source, IJavaProject project) throws Exception {
// String[] classpathEntries = getClasspathEntries(project);
// String unitName = uri.substring(uri.lastIndexOf("/"));
// return parse(source, uri, unitName, classpathEntries);
// }
//
// public static CompilationUnit parse(char[] source, String docURI, String unitName, String[] classpathEntries) throws Exception {
// ASTParser parser = ASTParser.newParser(AST.JLS11);
// Map<String, String> options = JavaCore.getOptions();
// JavaCore.setComplianceOptions(JavaCore.VERSION_11, options);
// parser.setCompilerOptions(options);
// parser.setKind(ASTParser.K_COMPILATION_UNIT);
// parser.setStatementsRecovery(true);
// parser.setBindingsRecovery(true);
// parser.setResolveBindings(true);
//
// String[] sourceEntries = new String[] {};
// parser.setEnvironment(classpathEntries, sourceEntries, null, false);
//
// parser.setUnitName(unitName);
// parser.setSource(source);
//
// CompilationUnit cu = (CompilationUnit) parser.createAST(null);
//
// return cu;
// }
public static CompilationUnit parse2(char[] source, String docURI, String unitName, IJavaProject project) throws Exception {
List<Classpath> classpaths = createClasspath(getClasspathEntries(project));
return parse2(source, docURI, unitName, classpaths, null);
@@ -294,7 +250,7 @@ public final class CompilationUnitCache implements DocumentContentProvider {
needToResolveBindings = false;
}
CompilationUnit cu = CUResolver.convert(unit, source, AST.JLS11, options, needToResolveBindings, DefaultWorkingCopyOwner.PRIMARY, flags);
CompilationUnit cu = CUResolver.convert(unit, source, AST.JLS14, options, needToResolveBindings, DefaultWorkingCopyOwner.PRIMARY, flags);
return cu;
}
@@ -331,7 +287,16 @@ public final class CompilationUnitCache implements DocumentContentProvider {
}
}
private void invalidateCuForJavaFile(String uriStr) {
logger.info("CU Cache: invalidate AST for {}", uriStr);
URI uri = URI.create(uriStr);
uriToCu.invalidate(uri);
}
private void invalidateProject(IJavaProject project) {
logger.info("CU Cache: invalidate project <{}>", project.getElementName());
Set<URI> docUris = projectToDocs.getIfPresent(project);
if (docUris != null) {
uriToCu.invalidateAll(docUris);
@@ -342,13 +307,13 @@ public final class CompilationUnitCache implements DocumentContentProvider {
@Override
public String fetchContent(URI uri) throws Exception {
if (documents != null) {
TextDocument document = documents.get(uri.toString());
if (documentService != null) {
TextDocument document = documentService.getLatestSnapshot(uri.toString());
if (document != null) {
return document.get(0, document.getLength());
return document.get();
}
}
return IOUtils.toString(uri);
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2020 Pivotal, Inc.
* Copyright (c) 2019, 2021 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
@@ -24,7 +24,6 @@ import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformati
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
@@ -34,12 +33,10 @@ public class BeanRefHyperlinkProvider implements XMLHyperlinkProvider {
private final JavaProjectFinder projectFinder;
private final SpringSymbolIndex symbolIndex;
private final SimpleTextDocumentService documents;
public BeanRefHyperlinkProvider(JavaProjectFinder projectFinder, SpringSymbolIndex symbolIndex, SimpleTextDocumentService documents) {
public BeanRefHyperlinkProvider(JavaProjectFinder projectFinder, SpringSymbolIndex symbolIndex) {
this.projectFinder = projectFinder;
this.symbolIndex = symbolIndex;
this.documents = documents;
}
@Override
@@ -47,11 +44,26 @@ public class BeanRefHyperlinkProvider implements XMLHyperlinkProvider {
Optional<IJavaProject> foundProject = this.projectFinder.find(doc.getId());
if (foundProject.isPresent()) {
final IJavaProject project = foundProject.get();
String projectLocation = project.getLocationUri() != null ? project.getLocationUri().toString() : "";
// make sure the project and the symbol location share the same prefix "file:///"
// looks like project locations are containing a "file:/" only
if (!projectLocation.startsWith("file:///")) {
projectLocation = "file:///" + projectLocation.substring("file:/".length());
}
// make sure that only exact project locations are matched
if (!projectLocation.endsWith("/")) {
projectLocation = projectLocation + "/";
}
List<SymbolInformation> symbols = symbolIndex.getSymbols(data -> symbolsFilter(data, attributeAt.getValue())).collect(Collectors.toList());
if (!symbols.isEmpty()) {
for (SymbolInformation symbol : symbols) {
Location location = symbol.getLocation();
if (project == documents.get(location.getUri())) {
String uri = location.getUri();
if (uri != null && uri.startsWith(projectLocation)) {
return location;
}
}
@@ -63,7 +75,7 @@ public class BeanRefHyperlinkProvider implements XMLHyperlinkProvider {
private boolean symbolsFilter(EnhancedSymbolInformation data, String beanId) {
SymbolAddOnInformation[] additionalInformation = data.getAdditionalInformation();
if (additionalInformation != null) {
if (beanId != null && additionalInformation != null) {
for (SymbolAddOnInformation info : additionalInformation) {
if (info instanceof BeansSymbolAddOnInformation) {
return beanId.equals(((BeansSymbolAddOnInformation)info).getBeanID());

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2020 Pivotal, Inc.
* Copyright (c) 2019, 2021 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
@@ -63,7 +63,8 @@ public class AppYamlQuickfixes {
DEPRECATED_PROPERTY = r.register("DEPRECATED_YAML_PROPERTY", (Object _params) -> {
DeprecatedPropertyData params = gson.fromJson((JsonElement)_params, DeprecatedPropertyData.class);
try {
TextDocument _doc = textDocumentService.getDocument(params.getUri());
TextDocument _doc = textDocumentService.getLatestSnapshot(params.getUri());
if (_doc != null) {
YamlDocument doc = new YamlDocument(_doc, structureProvider);
SNode root = doc.getStructure();