From 036b4e773c1f7b2ef16d28fc668c2bfe609ae1c4 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Thu, 4 Nov 2021 20:38:44 +0100 Subject: feat(lang): add example validation checks --- .../ProblemCrossrefProposalProvider.java | 4 +- .../language/resource/ReferenceCounter.java | 10 ++++- .../language/validation/ProblemValidator.java | 49 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java b/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java index 416535ce..f828e836 100644 --- a/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java +++ b/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java @@ -50,9 +50,7 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider return true; } if (rootModel instanceof Problem problem) { - var referenceCounts = referenceCounter.getReferenceCounts(problem); - var count = referenceCounts.get(eObject); - return count != null && count >= 2; + return referenceCounter.countReferences(problem, eObject) >= 2; } return true; } diff --git a/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java b/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java index 56186bc9..7525dfc6 100644 --- a/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java +++ b/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java @@ -16,7 +16,15 @@ public class ReferenceCounter { @Inject private IResourceScopeCache cache; - public Map getReferenceCounts(Problem problem) { + public int countReferences(Problem problem, EObject eObject) { + var count = getReferenceCounts(problem).get(eObject); + if (count == null) { + return 0; + } + return count; + } + + protected Map getReferenceCounts(Problem problem) { var resource = problem.eResource(); if (resource == null) { return doGetReferenceCounts(problem); diff --git a/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java b/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java index f2378df6..dfd386f5 100644 --- a/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java +++ b/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java @@ -3,6 +3,19 @@ */ package tools.refinery.language.validation; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.validation.Check; + +import com.google.inject.Inject; + +import tools.refinery.language.model.ProblemUtil; +import tools.refinery.language.model.problem.Node; +import tools.refinery.language.model.problem.Problem; +import tools.refinery.language.model.problem.ProblemPackage; +import tools.refinery.language.model.problem.Variable; +import tools.refinery.language.model.problem.VariableOrNodeArgument; +import tools.refinery.language.resource.ReferenceCounter; + /** * This class contains custom validation rules. * @@ -10,4 +23,40 @@ package tools.refinery.language.validation; * https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation */ public class ProblemValidator extends AbstractProblemValidator { + private static final String ISSUE_PREFIX = "tools.refinery.language.validation.ProblemValidator."; + + public static final String SINGLETON_VARIABLE_ISSUE = ISSUE_PREFIX + "SINGLETON_VARIABLE"; + + public static final String NON_UNIQUE_NODE_ISSUE = ISSUE_PREFIX + "NON_UNIQUE_NODE"; + + @Inject + private ReferenceCounter referenceCounter; + + @Check + public void checkUniqueVariable(VariableOrNodeArgument argument) { + var variableOrNode = argument.getVariableOrNode(); + if (variableOrNode instanceof Variable variable && ProblemUtil.isImplicitVariable(variable) + && !ProblemUtil.isSingletonVariable(variable)) { + var problem = EcoreUtil2.getContainerOfType(variable, Problem.class); + if (problem != null && referenceCounter.countReferences(problem, variable) <= 1) { + var name = variable.getName(); + var message = "Variable '%s' has only a single reference. Add another reference or mark is as a singleton variable: '_%s'" + .formatted(name, name); + warning(message, argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE, + INSIGNIFICANT_INDEX, SINGLETON_VARIABLE_ISSUE); + } + } + } + + @Check + public void checkNonUniqueNode(VariableOrNodeArgument argument) { + var variableOrNode = argument.getVariableOrNode(); + if (variableOrNode instanceof Node node && !ProblemUtil.isUniqueNode(node)) { + var name = node.getName(); + var message = "Only unique nodes can be referenced in predicates. Mark '%s' as unique with the declaration 'unique %s.'" + .formatted(name, name); + error(message, argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE, + INSIGNIFICANT_INDEX, NON_UNIQUE_NODE_ISSUE); + } + } } -- cgit v1.2.3-70-g09d2