@Check(CheckType.NORMAL) public void checkVariableUsageCounters(PatternBody body) { UnionFind<Variable> variableUnions = calculateEqualVariables(body); Map<Set<Variable>, VariableReferenceCount> unifiedRefCounters = new HashMap<>(); Map<Variable, VariableReferenceCount> individualRefCounters = new HashMap<>(); calculateUsageCounts(body, variableUnions, individualRefCounters, unifiedRefCounters); for (Variable var : body.getVariables()) { if (var instanceof ParameterRef) { checkParameterUsageCounter((ParameterRef) var, individualRefCounters, unifiedRefCounters, variableUnions, body); } else { checkLocalVariableUsageCounter(var, individualRefCounters, unifiedRefCounters, variableUnions); } } }
private void checkParameterUsageCounter(ParameterRef var, Map<Variable, VariableReferenceCount> individualCounters, Map<Set<Variable>, VariableReferenceCount> unifiedRefCounters, UnionFind<Variable> variableUnions, PatternBody body) { Variable parameter = var.getReferredParam(); VariableReferenceCount individualCounter = individualCounters.get(var); VariableReferenceCount unifiedCounter = unifiedRefCounters.get(variableUnions.getPartition(var)); if (individualCounter.getReferenceCount() == 0) { error(String.format("Parameter '%s' is never referenced in body '%s'.", parameter.getName(), getPatternBodyName(body)), parameter, PatternLanguagePackage.Literals.VARIABLE__NAME, IssueCodes.SYMBOLIC_VARIABLE_NEVER_REFERENCED); } else if (unifiedCounter.getReferenceCount(ReferenceType.POSITIVE) == 0) { error(String.format("Parameter '%s' has no enumerable reference in body '%s'.", var.getName(), getPatternBodyName(body)), parameter, PatternLanguagePackage.Literals.VARIABLE__NAME, IssueCodes.SYMBOLIC_VARIABLE_NO_POSITIVE_REFERENCE); } }
&& individualCounter.getReferenceCount() == 1 && !PatternLanguageHelper.isNamedSingleUse(var) && !PatternLanguageHelper.isUnnamedSingleUseVariable(var)) { warning(String.format( "Local variable '%s' is referenced only once. Is it mistyped? Start its name with '_' if intentional.", var.getName()), PatternLanguageHelper.getReferences(var).findAny().get(), PatternLanguagePackage.Literals.VARIABLE_REFERENCE__VAR, } else if (individualCounter.getReferenceCount() > 1 && PatternLanguageHelper.isNamedSingleUse(var)) { PatternLanguageHelper.getReferences(var) .forEach(ref -> error( String.format("Named single-use variable %s used multiple times.", var.getName()), ref, PatternLanguagePackage.Literals.VARIABLE_REFERENCE__VAR, } else if (unifiedCounter.getReferenceCount(ReferenceType.POSITIVE) == 0) { if (unifiedCounter.getReferenceCount(ReferenceType.NEGATIVE) == 0) { error(String.format( "Local variable '%s' appears in uncountable reference(s) only, thus its value cannot be determined.", var.getName()), var, PatternLanguagePackage.Literals.VARIABLE__NAME, && individualCounter.getReferenceCount() == 1 && !PatternLanguageHelper.isNamedSingleUse(var) && !PatternLanguageHelper.isUnnamedSingleUseVariable(var)) { warning(String.format( "Local variable '%s' will be quantified because it is used only here. Acknowledge this by prefixing its name with '_'.", var.getName()), PatternLanguageHelper.getReferences(var).findAny().get(), IssueCodes.LOCAL_VARIABLE_QUANTIFIED_REFERENCE); } else if (unifiedCounter.getReferenceCount() > 1) { error(String.format( "Local variable '%s' has no enumerable reference, thus its value cannot be determined.", var.getName()), PatternLanguageHelper.getReferences(var).findAny().get(),
return ReferenceType.POSITIVE; } else reportStrangeVariableRef(ref, constraint); } else if (rightIsVariable && !leftIsVariable) { if (ref.equals(constraint.getRightOperand())) { // this should always be true return ReferenceType.POSITIVE; } else reportStrangeVariableRef(ref, constraint); } else reportStrangeVariableRef(ref, constraint); } else if (constraint.getFeature() == CompareFeature.INEQUALITY) { return ReferenceType.READ_ONLY; } else reportStrangeVariableRef(ref, constraint); } else if (parent instanceof PatternCompositionConstraint && ((PatternCompositionConstraint) parent).isNegative()) {
final VariableReference ref = (VariableReference) obj; final Variable var = ref.getVariable(); final ReferenceType referenceClass = classifyReference(ref); individualRefCounters.get(var).incrementCounter(referenceClass); unifiedRefCounters.get(variableUnions.getPartition(var)).incrementCounter(referenceClass);