From 05c2bd349d8fec54f025a94572ced5d5225ed827 Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Fri, 30 Aug 2024 15:56:41 -0400 Subject: [PATCH] Use conditional logic to select the error message for an unmatched identifier based on whether it was a case-insensitive match (#1406) * Copy changes in 598-non-resolved-case-mismatch-warning into a fresh branch. * Spotless. * Move inner class to outer. New enum. Factory methods. Optionals. * Spotless. * More optimization. * More optimization. Spotless. * Don't return a warning. Only use conditional logic to determine what the error message should be based on whether it's due to a case insensitive match. * Reverse change to make warning public, since this is no longer needed. * Small tweak. --- .../cql/cql2elm/LibraryBuilder.java | 264 ++++++++++-------- .../cql/cql2elm/model/CompiledLibrary.java | 77 ++--- .../model/ResolvedIdentifierContext.java | 150 ++++++++++ .../cql/cql2elm/SemanticTests.java | 17 +- ...veCaseMismatchExistIdentifier_Issue598.cql | 10 + 5 files changed, 341 insertions(+), 177 deletions(-) create mode 100644 Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.java create mode 100644 Src/java/cql-to-elm/src/test/resources/org/cqframework/cql/cql2elm/IdentifierDoesNotResolveCaseMismatchExistIdentifier_Issue598.cql diff --git a/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/LibraryBuilder.java b/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/LibraryBuilder.java index dead0ca8b..953ac12af 100644 --- a/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/LibraryBuilder.java +++ b/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/LibraryBuilder.java @@ -795,7 +795,7 @@ public void removeExpression(ExpressionDef expDef) { } } - public Element resolve(String identifier) { + public ResolvedIdentifierContext resolve(String identifier) { return compiledLibrary.resolve(identifier); } @@ -2370,95 +2370,99 @@ public Expression resolveIdentifier(String identifier, boolean mustResolve) { return operandRef; } - Element element = resolve(identifier); + final ResolvedIdentifierContext resolvedIdentifierContext = resolve(identifier); + final Optional optElement = resolvedIdentifierContext.getExactMatchElement(); - if (element instanceof ExpressionDef) { - checkLiteralContext(); - ExpressionRef expressionRef = of.createExpressionRef().withName(((ExpressionDef) element).getName()); - expressionRef.setResultType(getExpressionDefResultType((ExpressionDef) element)); - if (expressionRef.getResultType() == null) { - // ERROR: - throw new IllegalArgumentException(String.format( - "Could not validate reference to expression %s because its definition contains errors.", - expressionRef.getName())); + if (optElement.isPresent()) { + final Element element = optElement.get(); + if (element instanceof ExpressionDef) { + checkLiteralContext(); + ExpressionRef expressionRef = of.createExpressionRef().withName(((ExpressionDef) element).getName()); + expressionRef.setResultType(getExpressionDefResultType((ExpressionDef) element)); + if (expressionRef.getResultType() == null) { + // ERROR: + throw new IllegalArgumentException(String.format( + "Could not validate reference to expression %s because its definition contains errors.", + expressionRef.getName())); + } + return expressionRef; } - return expressionRef; - } - if (element instanceof ParameterDef) { - checkLiteralContext(); - ParameterRef parameterRef = of.createParameterRef().withName(((ParameterDef) element).getName()); - parameterRef.setResultType(element.getResultType()); - if (parameterRef.getResultType() == null) { - // ERROR: - throw new IllegalArgumentException(String.format( - "Could not validate reference to parameter %s because its definition contains errors.", - parameterRef.getName())); + if (element instanceof ParameterDef) { + checkLiteralContext(); + ParameterRef parameterRef = of.createParameterRef().withName(((ParameterDef) element).getName()); + parameterRef.setResultType(element.getResultType()); + if (parameterRef.getResultType() == null) { + // ERROR: + throw new IllegalArgumentException(String.format( + "Could not validate reference to parameter %s because its definition contains errors.", + parameterRef.getName())); + } + return parameterRef; } - return parameterRef; - } - if (element instanceof ValueSetDef) { - checkLiteralContext(); - ValueSetRef valuesetRef = of.createValueSetRef().withName(((ValueSetDef) element).getName()); - valuesetRef.setResultType(element.getResultType()); - if (valuesetRef.getResultType() == null) { - // ERROR: - throw new IllegalArgumentException(String.format( - "Could not validate reference to valueset %s because its definition contains errors.", - valuesetRef.getName())); - } - if (isCompatibleWith("1.5")) { - valuesetRef.setPreserve(true); + if (element instanceof ValueSetDef) { + checkLiteralContext(); + ValueSetRef valuesetRef = of.createValueSetRef().withName(((ValueSetDef) element).getName()); + valuesetRef.setResultType(element.getResultType()); + if (valuesetRef.getResultType() == null) { + // ERROR: + throw new IllegalArgumentException(String.format( + "Could not validate reference to valueset %s because its definition contains errors.", + valuesetRef.getName())); + } + if (isCompatibleWith("1.5")) { + valuesetRef.setPreserve(true); + } + return valuesetRef; } - return valuesetRef; - } - if (element instanceof CodeSystemDef) { - checkLiteralContext(); - CodeSystemRef codesystemRef = of.createCodeSystemRef().withName(((CodeSystemDef) element).getName()); - codesystemRef.setResultType(element.getResultType()); - if (codesystemRef.getResultType() == null) { - // ERROR: - throw new IllegalArgumentException(String.format( - "Could not validate reference to codesystem %s because its definition contains errors.", - codesystemRef.getName())); + if (element instanceof CodeSystemDef) { + checkLiteralContext(); + CodeSystemRef codesystemRef = of.createCodeSystemRef().withName(((CodeSystemDef) element).getName()); + codesystemRef.setResultType(element.getResultType()); + if (codesystemRef.getResultType() == null) { + // ERROR: + throw new IllegalArgumentException(String.format( + "Could not validate reference to codesystem %s because its definition contains errors.", + codesystemRef.getName())); + } + return codesystemRef; } - return codesystemRef; - } - if (element instanceof CodeDef) { - checkLiteralContext(); - CodeRef codeRef = of.createCodeRef().withName(((CodeDef) element).getName()); - codeRef.setResultType(element.getResultType()); - if (codeRef.getResultType() == null) { - // ERROR: - throw new IllegalArgumentException(String.format( - "Could not validate reference to code %s because its definition contains errors.", - codeRef.getName())); + if (element instanceof CodeDef) { + checkLiteralContext(); + CodeRef codeRef = of.createCodeRef().withName(((CodeDef) element).getName()); + codeRef.setResultType(element.getResultType()); + if (codeRef.getResultType() == null) { + // ERROR: + throw new IllegalArgumentException(String.format( + "Could not validate reference to code %s because its definition contains errors.", + codeRef.getName())); + } + return codeRef; } - return codeRef; - } - if (element instanceof ConceptDef) { - checkLiteralContext(); - ConceptRef conceptRef = of.createConceptRef().withName(((ConceptDef) element).getName()); - conceptRef.setResultType(element.getResultType()); - if (conceptRef.getResultType() == null) { - // ERROR: - throw new IllegalArgumentException(String.format( - "Could not validate reference to concept %s because its definition contains error.", - conceptRef.getName())); + if (element instanceof ConceptDef) { + checkLiteralContext(); + ConceptRef conceptRef = of.createConceptRef().withName(((ConceptDef) element).getName()); + conceptRef.setResultType(element.getResultType()); + if (conceptRef.getResultType() == null) { + // ERROR: + throw new IllegalArgumentException(String.format( + "Could not validate reference to concept %s because its definition contains error.", + conceptRef.getName())); + } + return conceptRef; } - return conceptRef; - } - if (element instanceof IncludeDef) { - checkLiteralContext(); - LibraryRef libraryRef = new LibraryRef(); - libraryRef.setLocalId(of.nextId()); - libraryRef.setLibraryName(((IncludeDef) element).getLocalIdentifier()); - return libraryRef; + if (element instanceof IncludeDef) { + checkLiteralContext(); + LibraryRef libraryRef = new LibraryRef(); + libraryRef.setLocalId(of.nextId()); + libraryRef.setLibraryName(((IncludeDef) element).getLocalIdentifier()); + return libraryRef; + } } // If no other resolution occurs, and we are in a specific context, and there is a parameter with the same name @@ -2477,8 +2481,11 @@ public Expression resolveIdentifier(String identifier, boolean mustResolve) { if (mustResolve) { // ERROR: - throw new IllegalArgumentException( - String.format("Could not resolve identifier %s in the current library.", identifier)); + final String exceptionMessage = resolvedIdentifierContext + .warnCaseInsensitiveIfApplicable() + .orElse(String.format("Could not resolve identifier %s in the current library.", identifier)); + + throw new IllegalArgumentException(exceptionMessage); } return null; @@ -2524,9 +2531,11 @@ private static String lookupElementWarning(Object element) { */ public ParameterRef resolveImplicitContext() { if (!inLiteralContext() && inSpecificContext()) { - Element contextElement = resolve(currentExpressionContext()); - if (contextElement instanceof ParameterDef) { - ParameterDef contextParameter = (ParameterDef) contextElement; + ResolvedIdentifierContext resolvedIdentifierContext = resolve(currentExpressionContext()); + final Optional optParameterDef = + resolvedIdentifierContext.getElementOfType(ParameterDef.class); + if (optParameterDef.isPresent()) { + final ParameterDef contextParameter = optParameterDef.get(); checkLiteralContext(); ParameterRef parameterRef = of.createParameterRef().withName(contextParameter.getName()); @@ -2903,53 +2912,62 @@ public Expression resolveAccessor(Expression left, String memberIdentifier) { String libraryName = ((LibraryRef) left).getLibraryName(); CompiledLibrary referencedLibrary = resolveLibrary(libraryName); - Element element = referencedLibrary.resolve(memberIdentifier); + ResolvedIdentifierContext resolvedIdentifierContext = referencedLibrary.resolve(memberIdentifier); - if (element instanceof ExpressionDef) { - checkAccessLevel(libraryName, memberIdentifier, ((ExpressionDef) element).getAccessLevel()); - Expression result = - of.createExpressionRef().withLibraryName(libraryName).withName(memberIdentifier); - result.setResultType(getExpressionDefResultType((ExpressionDef) element)); - return result; - } + final Optional optElement = resolvedIdentifierContext.getExactMatchElement(); - if (element instanceof ParameterDef) { - checkAccessLevel(libraryName, memberIdentifier, ((ParameterDef) element).getAccessLevel()); - Expression result = - of.createParameterRef().withLibraryName(libraryName).withName(memberIdentifier); - result.setResultType(element.getResultType()); - return result; - } + if (optElement.isPresent()) { + final Element element = optElement.get(); - if (element instanceof ValueSetDef) { - checkAccessLevel(libraryName, memberIdentifier, ((ValueSetDef) element).getAccessLevel()); - ValueSetRef result = - of.createValueSetRef().withLibraryName(libraryName).withName(memberIdentifier); - result.setResultType(element.getResultType()); - return result; - } + if (element instanceof ExpressionDef) { + checkAccessLevel(libraryName, memberIdentifier, ((ExpressionDef) element).getAccessLevel()); + Expression result = of.createExpressionRef() + .withLibraryName(libraryName) + .withName(memberIdentifier); + result.setResultType(getExpressionDefResultType((ExpressionDef) element)); + return result; + } - if (element instanceof CodeSystemDef) { - checkAccessLevel(libraryName, memberIdentifier, ((CodeSystemDef) element).getAccessLevel()); - CodeSystemRef result = - of.createCodeSystemRef().withLibraryName(libraryName).withName(memberIdentifier); - result.setResultType(element.getResultType()); - return result; - } + if (element instanceof ParameterDef) { + checkAccessLevel(libraryName, memberIdentifier, ((ParameterDef) element).getAccessLevel()); + Expression result = + of.createParameterRef().withLibraryName(libraryName).withName(memberIdentifier); + result.setResultType(element.getResultType()); + return result; + } - if (element instanceof CodeDef) { - checkAccessLevel(libraryName, memberIdentifier, ((CodeDef) element).getAccessLevel()); - CodeRef result = of.createCodeRef().withLibraryName(libraryName).withName(memberIdentifier); - result.setResultType(element.getResultType()); - return result; - } + if (element instanceof ValueSetDef) { + checkAccessLevel(libraryName, memberIdentifier, ((ValueSetDef) element).getAccessLevel()); + ValueSetRef result = + of.createValueSetRef().withLibraryName(libraryName).withName(memberIdentifier); + result.setResultType(element.getResultType()); + return result; + } - if (element instanceof ConceptDef) { - checkAccessLevel(libraryName, memberIdentifier, ((ConceptDef) element).getAccessLevel()); - ConceptRef result = - of.createConceptRef().withLibraryName(libraryName).withName(memberIdentifier); - result.setResultType(element.getResultType()); - return result; + if (element instanceof CodeSystemDef) { + checkAccessLevel(libraryName, memberIdentifier, ((CodeSystemDef) element).getAccessLevel()); + CodeSystemRef result = of.createCodeSystemRef() + .withLibraryName(libraryName) + .withName(memberIdentifier); + result.setResultType(element.getResultType()); + return result; + } + + if (element instanceof CodeDef) { + checkAccessLevel(libraryName, memberIdentifier, ((CodeDef) element).getAccessLevel()); + CodeRef result = + of.createCodeRef().withLibraryName(libraryName).withName(memberIdentifier); + result.setResultType(element.getResultType()); + return result; + } + + if (element instanceof ConceptDef) { + checkAccessLevel(libraryName, memberIdentifier, ((ConceptDef) element).getAccessLevel()); + ConceptRef result = + of.createConceptRef().withLibraryName(libraryName).withName(memberIdentifier); + result.setResultType(element.getResultType()); + return result; + } } // ERROR: diff --git a/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/CompiledLibrary.java b/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/CompiledLibrary.java index 72785eabc..1fa44d700 100644 --- a/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/CompiledLibrary.java +++ b/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/CompiledLibrary.java @@ -33,11 +33,11 @@ public void setLibrary(Library library) { } private void checkNamespace(String identifier) { - Element existingElement = resolve(identifier); - if (existingElement != null) { + final ResolvedIdentifierContext existingResolvedIdentifierContext = resolve(identifier); + existingResolvedIdentifierContext.getExactMatchElement().ifPresent(element -> { throw new IllegalArgumentException( String.format("Identifier %s is already in use in this library.", identifier)); - } + }); } public void add(UsingDef using) { @@ -138,26 +138,25 @@ public void add(Conversion conversion) { conversions.add(conversion); } - public Element resolve(String identifier) { - return namespace.get(identifier); + public ResolvedIdentifierContext resolve(String identifier) { + if (namespace.containsKey(identifier)) { + return ResolvedIdentifierContext.exactMatch(identifier, namespace.get(identifier)); + } + + return namespace.entrySet().stream() + .filter(entry -> entry.getKey().equalsIgnoreCase(identifier)) + .map(Map.Entry::getValue) + .map(element -> ResolvedIdentifierContext.caseInsensitiveMatch(identifier, element)) + .findFirst() + .orElse(ResolvedIdentifierContext.caseInsensitiveMatch(identifier, null)); } public UsingDef resolveUsingRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof UsingDef) { - return (UsingDef) element; - } - - return null; + return resolveIdentifier(identifier, UsingDef.class); } public IncludeDef resolveIncludeRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof IncludeDef) { - return (IncludeDef) element; - } - - return null; + return resolveIdentifier(identifier, IncludeDef.class); } public String resolveIncludeAlias(VersionedIdentifier identifier) { @@ -177,57 +176,31 @@ public String resolveIncludeAlias(VersionedIdentifier identifier) { } public CodeSystemDef resolveCodeSystemRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof CodeSystemDef) { - return (CodeSystemDef) element; - } - - return null; + return resolveIdentifier(identifier, CodeSystemDef.class); } public ValueSetDef resolveValueSetRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof ValueSetDef) { - return (ValueSetDef) element; - } - - return null; + return resolveIdentifier(identifier, ValueSetDef.class); } public CodeDef resolveCodeRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof CodeDef) { - return (CodeDef) element; - } - - return null; + return resolveIdentifier(identifier, CodeDef.class); } public ConceptDef resolveConceptRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof ConceptDef) { - return (ConceptDef) element; - } - - return null; + return resolveIdentifier(identifier, ConceptDef.class); } public ParameterDef resolveParameterRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof ParameterDef) { - return (ParameterDef) element; - } - - return null; + return resolveIdentifier(identifier, ParameterDef.class); } public ExpressionDef resolveExpressionRef(String identifier) { - Element element = resolve(identifier); - if (element instanceof ExpressionDef) { - return (ExpressionDef) element; - } + return resolveIdentifier(identifier, ExpressionDef.class); + } - return null; + private T resolveIdentifier(String identifier, Class clazz) { + return resolve(identifier).resolveIdentifier(clazz); } public Iterable resolveFunctionRef(String identifier) { diff --git a/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.java b/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.java new file mode 100644 index 000000000..02ca5c1b2 --- /dev/null +++ b/Src/java/cql-to-elm/src/main/java/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.java @@ -0,0 +1,150 @@ +package org.cqframework.cql.cql2elm.model; + +import java.util.Objects; +import java.util.Optional; +import java.util.StringJoiner; +import org.hl7.elm.r1.CodeDef; +import org.hl7.elm.r1.CodeSystemDef; +import org.hl7.elm.r1.ConceptDef; +import org.hl7.elm.r1.ContextDef; +import org.hl7.elm.r1.Element; +import org.hl7.elm.r1.ExpressionDef; +import org.hl7.elm.r1.OperandDef; +import org.hl7.elm.r1.ParameterDef; +import org.hl7.elm.r1.TupleElementDefinition; +import org.hl7.elm.r1.ValueSetDef; + +/** + * Context for resolved identifiers containing the identifier, the resolved element (if non-null) as well as the type + * of matching done to retrieve the element, whether case-sensitive or case-insensitive. + */ +public class ResolvedIdentifierContext { + private final String identifier; + private final Element nullableElement; + + private enum ResolvedIdentifierMatchType { + EXACT, + CASE_INSENSITIVE + } + + // TODO: enum instead? + private final ResolvedIdentifierMatchType matchType; + + public static ResolvedIdentifierContext exactMatch(String identifier, Element nullableElement) { + return new ResolvedIdentifierContext(identifier, nullableElement, ResolvedIdentifierMatchType.EXACT); + } + + public static ResolvedIdentifierContext caseInsensitiveMatch(String identifier, Element nullableElement) { + return new ResolvedIdentifierContext(identifier, nullableElement, ResolvedIdentifierMatchType.CASE_INSENSITIVE); + } + + private ResolvedIdentifierContext( + String identifier, Element nullableElement, ResolvedIdentifierMatchType matchType) { + this.identifier = identifier; + this.nullableElement = nullableElement; + this.matchType = matchType; + } + + public Optional getExactMatchElement() { + if (isExactMatch()) { + return Optional.ofNullable(nullableElement); + } + + return Optional.empty(); + } + + private boolean isExactMatch() { + return ResolvedIdentifierMatchType.EXACT == matchType; + } + + public Optional warnCaseInsensitiveIfApplicable() { + if (nullableElement != null && !isExactMatch()) { + return getName(nullableElement) + .map(name -> + String.format("Could not find identifier: [%s]. Did you mean [%s]?", identifier, name)); + } + + return Optional.empty(); + } + + public T resolveIdentifier(Class clazz) { + return getExactMatchElement().filter(clazz::isInstance).map(clazz::cast).orElse(null); + } + + public Optional getElementOfType(Class clazz) { + if (clazz.isInstance(nullableElement)) { + return Optional.of(clazz.cast(nullableElement)); + } + + return Optional.empty(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + ResolvedIdentifierContext that = (ResolvedIdentifierContext) other; + return Objects.equals(identifier, that.identifier) + && Objects.equals(nullableElement, that.nullableElement) + && matchType == that.matchType; + } + + @Override + public int hashCode() { + return Objects.hash(identifier, nullableElement, matchType); + } + + @Override + public String toString() { + return new StringJoiner(", ", ResolvedIdentifierContext.class.getSimpleName() + "[", "]") + .add("identifier='" + identifier + "'") + .add("nullableElement=" + nullableElement) + .add("matchType=" + matchType) + .toString(); + } + + private static Optional getName(Element element) { + // TODO: consider other Elements that don't have getName() + if (element instanceof ExpressionDef) { + return Optional.of(((ExpressionDef) element).getName()); + } + + if (element instanceof ValueSetDef) { + return Optional.of(((ValueSetDef) element).getName()); + } + + if (element instanceof OperandDef) { + return Optional.of(((OperandDef) element).getName()); + } + + if (element instanceof TupleElementDefinition) { + return Optional.of(((TupleElementDefinition) element).getName()); + } + + if (element instanceof CodeDef) { + return Optional.of(((CodeDef) element).getName()); + } + + if (element instanceof ConceptDef) { + return Optional.of(((ConceptDef) element).getName()); + } + + if (element instanceof ParameterDef) { + return Optional.of(((ParameterDef) element).getName()); + } + + if (element instanceof CodeSystemDef) { + return Optional.of(((CodeSystemDef) element).getName()); + } + + if (element instanceof ContextDef) { + return Optional.of(((ContextDef) element).getName()); + } + + return Optional.empty(); + } +} diff --git a/Src/java/cql-to-elm/src/test/java/org/cqframework/cql/cql2elm/SemanticTests.java b/Src/java/cql-to-elm/src/test/java/org/cqframework/cql/cql2elm/SemanticTests.java index f950eda26..9de3d0840 100644 --- a/Src/java/cql-to-elm/src/test/java/org/cqframework/cql/cql2elm/SemanticTests.java +++ b/Src/java/cql-to-elm/src/test/java/org/cqframework/cql/cql2elm/SemanticTests.java @@ -755,8 +755,21 @@ void ifConditionalReturnTypes() throws IOException { } @Test - void issue863() throws IOException { - TestUtils.runSemanticTest("Issue863.cql", 0); + public void testIdentifierDoesNotResolveCaseMismatchExistIdentifier() throws IOException { + final CqlTranslator translator = + runSemanticTest("IdentifierDoesNotResolveCaseMismatchExistIdentifier_Issue598.cql", 2); + + final List errorMessages = + translator.getErrors().stream().map(Throwable::getMessage).collect(Collectors.toList()); + assertThat( + errorMessages, + contains( + "Could not resolve identifier NonExistent in the current library.", + "Could not find identifier: [IaMaDiFeReNtCaSe]. Did you mean [iAmAdIfErEnTcAsE]?")); + + final List warnings = + translator.getWarnings().stream().map(Throwable::getMessage).collect(Collectors.toList()); + assertThat(warnings, hasSize(0)); } private CqlTranslator runSemanticTest(String testFileName) throws IOException { diff --git a/Src/java/cql-to-elm/src/test/resources/org/cqframework/cql/cql2elm/IdentifierDoesNotResolveCaseMismatchExistIdentifier_Issue598.cql b/Src/java/cql-to-elm/src/test/resources/org/cqframework/cql/cql2elm/IdentifierDoesNotResolveCaseMismatchExistIdentifier_Issue598.cql new file mode 100644 index 000000000..294264c57 --- /dev/null +++ b/Src/java/cql-to-elm/src/test/resources/org/cqframework/cql/cql2elm/IdentifierDoesNotResolveCaseMismatchExistIdentifier_Issue598.cql @@ -0,0 +1,10 @@ +library TestIdentifierDoesNotResolveCaseMismatchExistIdentifier + +define "iAmAdIfErEnTcAsE" : 1 + +define doesNotResolveExact : + "NonExistent" + 1 + +define doesNotResolveCaseSensitive : +// "iAmAdIfErEnTcAsE" + 1 make sure comment isn't considered + "IaMaDiFeReNtCaSe" + 1