Goto defintion for releases
This commit is contained in:
@@ -21,6 +21,7 @@ import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlAstCache;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.ASTTypeCache;
|
||||
@@ -36,14 +37,14 @@ public class ConcourseDefinitionFinder extends SimpleDefinitionFinder<ConcourseL
|
||||
Flux<Location> handle(Node refNode, TextDocument doc, YamlFileAST ast);
|
||||
}
|
||||
|
||||
private final ConcourseModel models;
|
||||
private ASTTypeCache astTypes;
|
||||
private final ASTTypeCache astTypes;
|
||||
private Map<YType, Handler> handlers = new HashMap<>();
|
||||
private final YamlAstCache asts;
|
||||
|
||||
public ConcourseDefinitionFinder(ConcourseLanguageServer server, ConcourseModel models, PipelineYmlSchema schema) {
|
||||
super(server);
|
||||
this.models = models;
|
||||
this.astTypes = models.getAstTypeCache();
|
||||
this.asts = models.getAstCache();
|
||||
findByPath(schema.t_resource_name, ConcourseModel.RESOURCE_NAMES_PATH);
|
||||
findByPath(schema.t_maybe_resource_name, ConcourseModel.RESOURCE_NAMES_PATH);
|
||||
findByPath(schema.t_job_name, ConcourseModel.JOB_NAMES_PATH);
|
||||
@@ -58,7 +59,7 @@ public class ConcourseDefinitionFinder extends SimpleDefinitionFinder<ConcourseL
|
||||
* @param definitionsPath Path that points to all nodes within the same file corresponding
|
||||
* to definitions of nodes of the given type.
|
||||
*/
|
||||
private void findByPath(YType refType, YamlPath definitionsPath) {
|
||||
protected void findByPath(YType refType, YamlPath definitionsPath) {
|
||||
astTypes.addInterestingType(refType);
|
||||
Handler handler = (Node refNode, TextDocument doc, YamlFileAST ast) -> {
|
||||
String name = NodeUtil.asScalar(refNode);
|
||||
@@ -79,7 +80,7 @@ public class ConcourseDefinitionFinder extends SimpleDefinitionFinder<ConcourseL
|
||||
try {
|
||||
TextDocument doc = server.getTextDocumentService().get(params);
|
||||
if (doc!=null) {
|
||||
YamlFileAST ast = models.getSafeAst(doc, false);
|
||||
YamlFileAST ast = asts.getSafeAst(doc, false);
|
||||
if (ast!=null) {
|
||||
Node refNode = ast.findNode(doc.toOffset(params.getPosition()));
|
||||
if (refNode!=null) {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ConcourseLanguageServer extends SimpleLanguageServer {
|
||||
YamlStructureProvider structureProvider = YamlStructureProvider.DEFAULT;
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
ConcourseModel models = new ConcourseModel(this);
|
||||
YamlASTProvider currentAsts = models.getAstProvider(false);
|
||||
YamlASTProvider currentAsts = models.getAstCache().getAstProvider(false);
|
||||
private SchemaSpecificPieces forPipelines;
|
||||
private SchemaSpecificPieces forTasks;
|
||||
private final YamlQuickfixes yamlQuickfixes;
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlASTProvider;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlAstCache;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlParser;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.ASTRootCursor;
|
||||
@@ -52,8 +53,8 @@ import org.springframework.ide.vscode.commons.yaml.schema.YTypeFactory.YBeanUnio
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.constraints.Constraint;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypedProperty;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
|
||||
import org.springframework.ide.vscode.commons.yaml.util.StaleFallbackCache;
|
||||
import org.springframework.ide.vscode.commons.yaml.util.Streams;
|
||||
import org.springframework.ide.vscode.concourse.util.StaleFallbackCache;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
@@ -112,7 +113,7 @@ public class ConcourseModel {
|
||||
if (job!=null) {
|
||||
//Only check if the job exists. Otherwise the extra checks will show 'redundant' errors (e.g.
|
||||
// complaining that 'some-job' doesn't ineract with a resource (because the resource doesn't exist).
|
||||
YamlFileAST root = this.getSafeAst(dc.getDocument());
|
||||
YamlFileAST root = asts.getSafeAst(dc.getDocument());
|
||||
if (root!=null) {
|
||||
Node stepNode = path.dropLast().traverseToNode(root);
|
||||
if (stepNode!=null) {
|
||||
@@ -256,9 +257,7 @@ public class ConcourseModel {
|
||||
valueAt("name")
|
||||
);
|
||||
|
||||
private final YamlParser parser;
|
||||
private final StaleFallbackCache<String, YamlFileAST> asts = new StaleFallbackCache<>();
|
||||
|
||||
private final YamlAstCache asts = new YamlAstCache();
|
||||
private final ASTTypeCache astTypes = new ASTTypeCache();
|
||||
|
||||
private ResourceTypeRegistry resourceTypes;
|
||||
@@ -268,8 +267,6 @@ public class ConcourseModel {
|
||||
private YBeanUnionType stepType;
|
||||
|
||||
public ConcourseModel(SimpleLanguageServer languageServer) {
|
||||
Yaml yaml = new Yaml();
|
||||
this.parser = new YamlParser(yaml);
|
||||
this.snippetBuilderFactory = languageServer::createSnippetBuilder;
|
||||
}
|
||||
|
||||
@@ -368,7 +365,7 @@ public class ConcourseModel {
|
||||
public Node getParentPropertyNode(String propName, DynamicSchemaContext dc) {
|
||||
YamlPath path = dc.getPath();
|
||||
if (path!=null) {
|
||||
YamlFileAST root = this.getSafeAst(dc.getDocument());
|
||||
YamlFileAST root = asts.getSafeAst(dc.getDocument());
|
||||
if (root!=null) {
|
||||
return path.dropLast().append(YamlPathSegment.valueAt(propName)).traverseToNode(root);
|
||||
}
|
||||
@@ -402,7 +399,7 @@ public class ConcourseModel {
|
||||
if (doc!=null) {
|
||||
String uri = doc.getUri();
|
||||
if (uri!=null) {
|
||||
YamlFileAST ast = getAst(doc, true);
|
||||
YamlFileAST ast = asts.getAst(doc, true);
|
||||
return astFunction.apply(ast);
|
||||
}
|
||||
}
|
||||
@@ -414,36 +411,6 @@ public class ConcourseModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
public YamlFileAST getSafeAst(IDocument doc) {
|
||||
return getSafeAst(doc, true);
|
||||
}
|
||||
|
||||
public YamlFileAST getAst(IDocument doc, boolean allowStaleAst) throws Exception {
|
||||
return getAstProvider(allowStaleAst).getAST(doc);
|
||||
}
|
||||
|
||||
public YamlASTProvider getAstProvider(boolean allowStaleAsts) {
|
||||
return (IDocument doc) -> {
|
||||
String uri = doc.getUri();
|
||||
if (uri!=null) {
|
||||
return asts.get(uri, doc.getVersion(), allowStaleAsts, () -> {
|
||||
return parser.getAST(doc);
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
public YamlFileAST getSafeAst(IDocument doc, boolean allowStaleAst) {
|
||||
if (doc!=null) {
|
||||
try {
|
||||
return getAst(doc, allowStaleAst);
|
||||
} catch (Exception e) {
|
||||
//ignored
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ASTTypeCache getAstTypeCache() {
|
||||
return astTypes;
|
||||
@@ -458,4 +425,8 @@ public class ConcourseModel {
|
||||
this.stepType = step;
|
||||
}
|
||||
|
||||
public YamlAstCache getAstCache() {
|
||||
return this.asts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.ide.vscode.commons.util.ValueParser;
|
||||
import org.springframework.ide.vscode.commons.util.ValueParsers;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlAstCache;
|
||||
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
|
||||
@@ -134,6 +135,7 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
private final ResourceTypeRegistry resourceTypes = new ResourceTypeRegistry();
|
||||
|
||||
private final ConcourseModel models;
|
||||
private final YamlAstCache asts;
|
||||
|
||||
public final YType t_semver = f.yatomic("Semver")
|
||||
.parseWith(ValueParsers.NE_STRING); //TODO: use real semver parser.
|
||||
@@ -155,9 +157,9 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
|
||||
private List<YType> definitionTypes = new ArrayList<>();
|
||||
|
||||
|
||||
public PipelineYmlSchema(ConcourseModel models) {
|
||||
this.models = models;
|
||||
this.asts = models.getAstCache();
|
||||
models.setResourceTypeRegistry(resourceTypes);
|
||||
TYPE_UTIL = f.TYPE_UTIL;
|
||||
|
||||
@@ -659,7 +661,7 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
private String getSiblingPropertyValue(DynamicSchemaContext dc, String propName) {
|
||||
YamlPath path = dc.getPath();
|
||||
if (path!=null) {
|
||||
YamlFileAST root = models.getSafeAst(dc.getDocument());
|
||||
YamlFileAST root = asts.getSafeAst(dc.getDocument());
|
||||
if (root!=null) {
|
||||
return NodeUtil.asScalar(path.append(YamlPathSegment.valueAt(propName)).traverseToNode(root));
|
||||
}
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.concourse.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
/**
|
||||
* A simple cache implementation that provides an option for lookups to fallback
|
||||
* to a 'stale' cache entry when computing a current one fails.
|
||||
*/
|
||||
public class StaleFallbackCache<K, V>{
|
||||
|
||||
private static class Versioned<T> {
|
||||
int version;
|
||||
T it;
|
||||
public Versioned(int version, T it) {
|
||||
super();
|
||||
this.version = version;
|
||||
this.it = it;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((it == null) ? 0 : it.hashCode());
|
||||
result = prime * result + version;
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Versioned other = (Versioned) obj;
|
||||
if (it == null) {
|
||||
if (other.it != null)
|
||||
return false;
|
||||
} else if (!it.equals(other.it))
|
||||
return false;
|
||||
if (version != other.version)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Versioned [version=" + version + ", it=" + it + "]";
|
||||
}
|
||||
}
|
||||
|
||||
Map<K, V> staleEntries = new HashMap<>();
|
||||
Cache<K, Versioned<CompletableFuture<V>>> latestEntries = CacheBuilder.newBuilder().build();
|
||||
|
||||
public synchronized V get(K key, int version, boolean allowStaleEntries, Callable<? extends V> valueLoader) throws Exception {
|
||||
Versioned<CompletableFuture<V>> latest = latestEntries.get(key, () -> new Versioned<>(version, load(valueLoader)));
|
||||
if (latest.version!=version) {
|
||||
latestEntries.invalidate(key);
|
||||
keepStaleBackup(key, latest);
|
||||
latest = latestEntries.get(key, () -> new Versioned<>(version, load(valueLoader)));
|
||||
}
|
||||
if (!allowStaleEntries) {
|
||||
return future_get(version, latest);
|
||||
} else {
|
||||
if (latest.it.isCompletedExceptionally()) {
|
||||
V staleValue = staleEntries.get(key);
|
||||
if (staleValue!=null) {
|
||||
return staleValue;
|
||||
}
|
||||
}
|
||||
return future_get(latest.it);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a stale entry is found in the 'latest' map. This method is
|
||||
* responsible for determining if the entry should be kept as a staleBackup,
|
||||
* and store it.
|
||||
*/
|
||||
private void keepStaleBackup(K key, Versioned<CompletableFuture<V>> latest) {
|
||||
try {
|
||||
staleEntries.put(key, latest.it.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
//ignore: This means its a 'bad' entry and so we don't want to keep it
|
||||
// as a 'stale backup'.
|
||||
}
|
||||
}
|
||||
|
||||
private V future_get(int wantedVersion, Versioned<CompletableFuture<V>> versioned) throws Exception {
|
||||
Assert.isLegal(wantedVersion==versioned.version);
|
||||
return future_get(versioned.it);
|
||||
}
|
||||
|
||||
private V future_get(CompletableFuture<V> f) throws Exception {
|
||||
try {
|
||||
return f.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw e;
|
||||
} catch (ExecutionException e) {
|
||||
throw ExceptionUtil.exception(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<V> load(Callable<? extends V> valueLoader) {
|
||||
CompletableFuture<V> future = new CompletableFuture<V>();
|
||||
try {
|
||||
V value = valueLoader.call();
|
||||
Assert.isNotNull(value);
|
||||
future.complete(value);
|
||||
} catch (Throwable e) {
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user