From 3abcf3abed1e74aec579159088e73291e6320630 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Wed, 3 May 2017 10:59:20 -0400 Subject: [PATCH] Routes advanced validation --- .../ide/vscode/commons/yaml/ast/NodeUtil.java | 5 +-- .../testharness/LanguageServerHarness.java | 8 ++--- .../manifest/yaml/ManifestConstraints.java | 32 +++++++++++++++++++ .../yaml/ManifestYamlSchemaProblemsTypes.java | 3 ++ .../manifest/yaml/ManifestYmlSchema.java | 2 +- 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestConstraints.java diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java index 7336c21e2..e6aa0d844 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/NodeUtil.java @@ -86,8 +86,9 @@ public class NodeUtil { * Get the scalar values of all keys of the given {@link MappingNode} as Strings. * Any non-scalar keys are silently ignored. */ - public static Set getScalarKeys(MappingNode mapNode) { - if (mapNode!=null) { + public static Set getScalarKeys(Node node) { + if (node instanceof MappingNode) { + MappingNode mapNode = (MappingNode) node; ImmutableSet.Builder builder = ImmutableSet.builder(); for (NodeTuple entry : mapNode.getValue()) { String key = NodeUtil.asScalar(entry.getKeyNode()); diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java index e6a01d861..65038befc 100644 --- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java +++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java @@ -46,7 +46,7 @@ import org.eclipse.lsp4j.DiagnosticSeverity; import org.eclipse.lsp4j.DidChangeTextDocumentParams; import org.eclipse.lsp4j.DidOpenTextDocumentParams; import org.eclipse.lsp4j.DocumentSymbolParams; -import org.eclipse.lsp4j.ExecuteCommandCapabilites; +import org.eclipse.lsp4j.ExecuteCommandCapabilities; import org.eclipse.lsp4j.ExecuteCommandParams; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.InitializeParams; @@ -68,7 +68,7 @@ import org.eclipse.lsp4j.TextDocumentSyncKind; import org.eclipse.lsp4j.TextDocumentSyncOptions; import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4j.VersionedTextDocumentIdentifier; -import org.eclipse.lsp4j.WorkspaceClientCapabilites; +import org.eclipse.lsp4j.WorkspaceClientCapabilities; import org.eclipse.lsp4j.WorkspaceEdit; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.services.LanguageClientAware; @@ -172,9 +172,9 @@ public class LanguageServerHarness { CompletionCapabilities completionCap = new CompletionCapabilities(new CompletionItemCapabilities(true)); textCap.setCompletion(completionCap); clientCap.setTextDocument(textCap); - WorkspaceClientCapabilites workspaceCap = new WorkspaceClientCapabilites(); + WorkspaceClientCapabilities workspaceCap = new WorkspaceClientCapabilities(); workspaceCap.setApplyEdit(true); - ExecuteCommandCapabilites exeCap = new ExecuteCommandCapabilites(); + ExecuteCommandCapabilities exeCap = new ExecuteCommandCapabilities(); exeCap.setDynamicRegistration(true); workspaceCap.setExecuteCommand(exeCap); clientCap.setWorkspace(workspaceCap); diff --git a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestConstraints.java b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestConstraints.java new file mode 100644 index 000000000..235f04552 --- /dev/null +++ b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestConstraints.java @@ -0,0 +1,32 @@ +package org.springframework.ide.vscode.manifest.yaml; + +import java.util.Arrays; +import java.util.Set; + +import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl; +import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil; +import org.springframework.ide.vscode.commons.yaml.schema.constraints.Constraint; +import org.yaml.snakeyaml.nodes.MappingNode; +import org.yaml.snakeyaml.nodes.Node; + +public class ManifestConstraints { + + public static Constraint mutuallyExclusive(String... propertyIds) { + return (dc, parent, node, type, problems) -> { + Set keys = NodeUtil.getScalarKeys(parent); + Arrays.stream(propertyIds).filter(id -> keys.contains(id)).findFirst().ifPresent(propertyId -> { + // Find key node, because the node parameter is the value node + MappingNode mapNode = (MappingNode) parent; + mapNode.getValue().stream().filter(t -> t.getValueNode() == node).findFirst().ifPresent(t -> { + Node keyNode = t.getKeyNode(); + int start = keyNode.getStartMark().getIndex(); + int end = keyNode.getEndMark().getIndex(); + problems.accept( + new ReconcileProblemImpl(ManifestYamlSchemaProblemsTypes.MUTUALLY_EXCLUSIVE_PROPERTY_PROBLEM, + "Property cannot co-exist with property '" + propertyId + "'", start, end - start)); + });; + }); + }; + } + +} diff --git a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlSchemaProblemsTypes.java b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlSchemaProblemsTypes.java index 477c8ad40..64f9b1585 100644 --- a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlSchemaProblemsTypes.java +++ b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlSchemaProblemsTypes.java @@ -26,4 +26,7 @@ public class ManifestYamlSchemaProblemsTypes { public static final ProblemType UNKNOWN_DOMAIN_PROBLEM = problemType("UnknownDomainProblem", ProblemSeverity.WARNING); + public static final ProblemType MUTUALLY_EXCLUSIVE_PROPERTY_PROBLEM = problemType("MutuallyExclusiveProperty", + ProblemSeverity.ERROR); + } diff --git a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java index 70f4277d6..32accaa0a 100644 --- a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java +++ b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java @@ -71,7 +71,7 @@ public class ManifestYmlSchema implements YamlSchema { } YAtomicType t_domain = f.yatomic("Domain"); - + t_domain.require(ManifestConstraints.mutuallyExclusive("routes")); if (domainsProvider != null) { t_domain.addHintProvider(domainsProvider); }