Repository: elm-tooling/elm-language-server (ts)

Issue:
References for let functions are incorrect
It looks like it searches the entire file for references, instead of just the let expr.

Pull request:
Fix references for union constructors and functions
Fixes #519. 

Patch:
diff --git a/jest.config.js b/jest.config.js
index d25e7a3..089125d 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -3,7 +3,7 @@ module.exports = {
   testEnvironment: "node",
   testMatch: ["**/?(*.)+(spec|test).[tj]s?(x)"],
   collectCoverage: true,
-  coverageReporters: ["lcov", "text", "json"],
+  coverageReporters: ["lcov"],
   setupFilesAfterEnv: ["<rootDir>/test/jest.setup.ts"],
   coveragePathIgnorePatterns: ["<rootDir>/test/"],
 };
diff --git a/package.json b/package.json
index e5cc669..d04ee1f 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
     "out"
   ],
   "engines": {
-    "node": ">=12.0.0"
+    "node": ">=10.0.0"
   },
   "repository": {
     "type": "git",
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 25f45c4..d882e9d 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -624,7 +624,8 @@ export class Program implements IProgram {
 
       // We could track this using the separate `testDirectories`
       // But those are just hardcoded to ./tests anyways, so this should be fine
-      const isTestDir = sourceDir.endsWith("tests");
+      const isTestDir =
+        matchingPath.includes("tests") || matchingPath.includes("Tests");
       if (isTestDir) {
         project.testModuleToUriMap.set(
           moduleName,
diff --git a/src/compiler/references.ts b/src/compiler/references.ts
index d952ecb..ea3bea7 100644
--- a/src/compiler/references.ts
+++ b/src/compiler/references.ts
@@ -42,9 +42,12 @@ export class References {
                 }
               }
 
-              const functionNameNode = TreeUtils.getFunctionNameNodeFromDefinition(
-                definitionNode.node,
-              );
+              const functionNameNode =
+                TreeUtils.getFunctionNameNodeFromDefinition(
+                  definitionNode.node,
+                ) ?? definitionNode.node.type === "lower_pattern"
+                  ? definitionNode.node
+                  : undefined;
               if (functionNameNode) {
                 const functionName = functionNameNode.text;
                 if (refSourceTree.writeable) {
@@ -54,18 +57,16 @@ export class References {
                   });
                 }
 
-                const localFunctions =
-                  definitionNode.node.parent?.parent &&
-                  definitionNode.node.parent?.parent.type === "let_in_expr" &&
-                  definitionNode.node.parent?.parent.lastNamedChild
-                    ? this.findFunctionCalls(
-                        definitionNode.node.parent.parent.lastNamedChild,
-                        functionName,
-                      )
-                    : this.findFunctionCalls(
-                        refSourceTree.tree.rootNode,
-                        functionName,
-                      );
+                const letParent = TreeUtils.findParentOfType(
+                  "let_in_expr",
+                  definitionNode.node,
+                );
+                const localFunctions = letParent
+                  ? this.findFunctionCalls(letParent, functionName)
+                  : this.findFunctionCalls(
+                      refSourceTree.tree.rootNode,
+                      functionName,
+                    );
 
                 if (localFunctions && refSourceTree.writeable) {
                   references.push(
@@ -79,7 +80,7 @@ export class References {
                   refSourceTree.tree,
                   functionName,
                 );
-                if (isExposedFunction) {
+                if (isExposedFunction && !letParent) {
                   const moduleDeclarationNode = TreeUtils.findModuleDeclaration(
                     refSourceTree.tree,
                   );
@@ -608,22 +609,34 @@ export class References {
                   continue;
                 }
 
+                const otherSourceFile = program.getSourceFile(uri);
+
+                if (!otherSourceFile) {
+                  continue;
+                }
+
                 const moduleName = moduleNameNode.text;
 
+                const importedModuleAlias =
+                  TreeUtils.findImportAliasOfModule(
+                    moduleName,
+                    otherSourceFile.tree,
+                  ) ?? moduleName;
+
                 const allImports = imports[uri];
                 const found =
                   allImports.getConstructor(nameNode.text, moduleName)[0] ??
                   allImports.getConstructor(
-                    `${moduleNameNode.text}.${nameNode.text}`,
+                    `${importedModuleAlias}.${nameNode.text}`,
                     moduleName,
                   )[0];
 
                 if (found && found.type === "UnionConstructor") {
-                  const treeToCheck = forest.getByUri(uri);
-                  if (treeToCheck && treeToCheck.writeable) {
+                  if (otherSourceFile.writeable) {
                     const unionConstructorCallsFromOtherFiles = TreeUtils.findUnionConstructorCalls(
-                      treeToCheck.tree,
+                      otherSourceFile.tree,
                       nameNode.text,
+                      importedModuleAlias,
                     );
                     if (unionConstructorCallsFromOtherFiles) {
                       references.push(
@@ -717,7 +730,10 @@ export class References {
     node: SyntaxNode,
     functionName: string,
   ): SyntaxNode[] | undefined {
-    const functions = this.findAllFunctionCallsAndParameters(node);
+    const functions = [
+      ...this.findAllFunctionCallsAndParameters(node).concat(),
+      ...node.descendantsOfType("record_base_identifier"),
+    ];
     const result = functions
       .filter((a) => a.text === functionName)
       .map((a) => a.lastChild!);
diff --git a/src/providers/astProvider.ts b/src/providers/astProvider.ts
index d5dc247..d7d197d 100644
--- a/src/providers/astProvider.ts
+++ b/src/providers/astProvider.ts
@@ -143,7 +143,7 @@ export class ASTProvider {
     );
 
     oldNodes.forEach((node) => {
-      if (node && !newIds.has(node.id)) {
+      if (!newIds.has(node.id)) {
         params.program.getTypeCache().invalidateValueDeclaration(node);
         params.program.getTypeCache().invalidateTypeAnnotation(node);
         params.program.getTypeCache().invalidateTypeOrTypeAlias(node);
diff --git a/src/providers/codeAction/addMissingCaseBranches.ts b/src/providers/codeAction/addMissingCaseBranches.ts
index 4eb5800..fe84a1e 100644
--- a/src/providers/codeAction/addMissingCaseBranches.ts
+++ b/src/providers/codeAction/addMissingCaseBranches.ts
@@ -45,23 +45,17 @@ function getEdits(params: ICodeActionParams, range: Range): TextEdit[] {
   );
 
   if (nodeAtPosition.type === "case_of_expr") {
-    const branches = nodeAtPosition.namedChildren.filter(
-      (n) => n.type === "case_of_branch",
-    );
-    const patterns = branches
+    const patterns = nodeAtPosition.namedChildren
+      .filter((n) => n.type === "case_of_branch")
       .map((branch) => branch.childForFieldName("pattern"))
       .filter(Utils.notUndefinedOrNull.bind(getEdits));
 
-    const branchIndent = getSpaces(branches[0].startPosition.column);
-    const branchExprIndent = getSpaces(
-      branches[0].childForFieldName("expr")?.startPosition.column ??
-        branches[0].startPosition.column + 4,
-    );
+    const indent = getSpaces(nodeAtPosition.startPosition.column);
 
     const edit = PatternMatches.missing(patterns, params.program).reduce(
       (edit, missing) =>
         edit +
-        `\n\n${branchIndent}${missing} ->\n${branchExprIndent}Debug.todo "branch '${missing}' not implemented"`,
+        `\n\n${indent}${indent}${missing} ->\n${indent}${indent}${indent}${indent}`,
       "",
     );
 
diff --git a/src/providers/codeLensProvider.ts b/src/providers/codeLensProvider.ts
index 2de4a98..aa2dc07 100644
--- a/src/providers/codeLensProvider.ts
+++ b/src/providers/codeLensProvider.ts
@@ -285,8 +285,11 @@ export class CodeLensProvider {
       }
     });
 
-    TreeUtils.descendantsOfType(tree.rootNode, "value_declaration").forEach(
-      (node) => {
+    TreeUtils.descendantsOfType(tree.rootNode, "value_declaration")
+      .filter(
+        (valueDeclaration) => !valueDeclaration.childForFieldName("pattern"),
+      )
+      .forEach((node) => {
         codeLens.push(
           this.createReferenceCodeLens(
             node.previousNamedSibling?.type === "type_annotation"
@@ -295,8 +298,7 @@ export class CodeLensProvider {
             uri,
           ),
         );
-      },
-    );
+      });
 
     const moduleNameNode = TreeUtils.getModuleNameNode(tree);
     if (moduleNameNode && moduleNameNode.lastChild) {
diff --git a/src/providers/completionProvider.ts b/src/providers/completionProvider.ts
index 2d39b91..ff7debd 100644
--- a/src/providers/completionProvider.ts
+++ b/src/providers/completionProvider.ts
@@ -28,7 +28,6 @@ import { TypeChecker } from "../compiler/typeChecker";
 import escapeStringRegexp from "escape-string-regexp";
 import { TRecord } from "../compiler/typeInference";
 import { ICompletionParams } from "./paramsExtensions";
-import { Utils } from "../util/utils";
 
 export type CompletionResult =
   | CompletionItem[]
@@ -1237,49 +1236,31 @@ export class CompletionProvider {
       return result;
     }
 
-    let alreadyImported = false;
+    let alreadyImported = true;
 
-    const matchedSourceFiles: ISourceFile[] = [];
+    // Try to find the module definition that is already imported
+    const definitionNode = checker.findDefinition(node, sourceFile).symbol;
 
-    const imports =
-      sourceFile.symbolLinks
-        ?.get(sourceFile.tree.rootNode)
-        ?.getAll(targetModule)
-        ?.filter((symbol) => symbol.type === "Import") ?? [];
+    let moduleTree: ISourceFile | undefined;
 
-    if (imports.length > 0) {
-      matchedSourceFiles.push(
-        ...imports
-          .map((imp) => {
-            const moduleName =
-              imp.node.childForFieldName("moduleName")?.text ?? "";
-
-            return program.getSourceFileOfImportableModule(
-              sourceFile,
-              moduleName,
-            );
-          })
-          .filter(Utils.notUndefined.bind(this)),
-      );
-
-      alreadyImported = true;
-    } else if (!checker.getAllImports(sourceFile).getModule(targetModule)) {
-      // Try to find a module that may not be imported
-      const moduleSourceFile = program.getSourceFileOfImportableModule(
+    if (
+      definitionNode?.node &&
+      TreeUtils.findParentOfType("module_declaration", definitionNode.node)
+    ) {
+      moduleTree = program.getSourceFile(definitionNode.node.tree.uri);
+    } else {
+      // Try to find this module in the forest to import
+      moduleTree = program.getSourceFileOfImportableModule(
         sourceFile,
         targetModule,
       );
-
-      if (moduleSourceFile) {
-        matchedSourceFiles.push(moduleSourceFile);
-        alreadyImported = false;
-      }
+      alreadyImported = false;
     }
 
-    // Get exposed values
-    matchedSourceFiles
-      .flatMap(ImportUtils.getPossibleImportsOfTree.bind(this))
-      .forEach((value) => {
+    if (moduleTree) {
+      // Get exposed values
+      const imports = ImportUtils.getPossibleImportsOfTree(moduleTree);
+      imports.forEach((value) => {
         const markdownDocumentation = HintHelper.createHint(value.node);
         let additionalTextEdits: TextEdit[] | undefined;
         let detail: string | undefined;
@@ -1320,6 +1301,7 @@ export class CompletionProvider {
             break;
         }
       });
+    }
 
     return result;
   }
diff --git a/src/util/treeUtils.ts b/src/util/treeUtils.ts
index 5d472c6..bfb1521 100644
--- a/src/util/treeUtils.ts
+++ b/src/util/treeUtils.ts
@@ -100,10 +100,7 @@ export class TreeUtils {
         module,
       );
       if (exposingList) {
-        const doubleDot = this.findFirstNamedChildOfType(
-          "double_dot",
-          exposingList,
-        );
+        const doubleDot = exposingList.childForFieldName("doubleDot");
         if (doubleDot) {
           return true;
         }
@@ -187,6 +184,7 @@ export class TreeUtils {
   public static findUnionConstructorCalls(
     tree: Tree,
     unionConstructorName: string,
+    moduleNamePrefix?: string,
   ): SyntaxNode[] | undefined {
     const upperCaseQid = TreeUtils.descendantsOfType(
       tree.rootNode,
@@ -195,9 +193,9 @@ export class TreeUtils {
     if (upperCaseQid.length > 0) {
       const result = upperCaseQid.filter(
         (a) =>
-          a.firstChild !== null &&
-          a.firstChild.type === "upper_case_identifier" &&
-          a.firstChild.text === unionConstructorName &&
+          (a.text === unionConstructorName ||
+            (moduleNamePrefix &&
+              a.text === `${moduleNamePrefix}.${unionConstructorName}`)) &&
           a.parent &&
           a.parent.type !== "type_ref",
       );


Test patch:
diff --git a/test/codeActionTests/addMissingCaseBranches.test.ts b/test/codeActionTests/addMissingCaseBranches.test.ts
deleted file mode 100644
index c84d176..0000000
--- a/test/codeActionTests/addMissingCaseBranches.test.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import { testCodeAction } from "./codeActionTestBase";
-
-describe("add missing record field code action", () => {
-  it("should work with a normal case expr", async () => {
-    const source = `
---@ Test.elm
-module Test exposing (..)
-
-func a =
-    case a of
-    --^
-        1 ->
-            ""
-
-        2 -> 
-            ""
-
-`;
-
-    const expectedSource = `
---@ Test.elm
-module Test exposing (..)
-
-func a =
-    case a of
-        1 ->
-            ""
-
-        2 -> 
-            ""
-
-        _ ->
-            Debug.todo "branch '_' not implemented"
-
-`;
-
-    await testCodeAction(
-      source,
-      [{ title: "Add missing case branches" }],
-      expectedSource,
-    );
-  });
-
-  it("should work with a nested case expr", async () => {
-    const source = `
---@ Test.elm
-module Test exposing (..)
-
-type Maybe a = Just a | Nothing
-
-func a b =
-    case a of
-        1 ->
-            ""
-
-        2 ->
-            case b of
-            --^
-                Nothing ->
-                    ""
-        
-        _ ->
-            ""
-    `;
-
-    const expectedSource = `
---@ Test.elm
-module Test exposing (..)
-
-type Maybe a = Just a | Nothing
-
-func a b =
-    case a of
-        1 ->
-            ""
-
-        2 ->
-            case b of
-                Nothing ->
-                    ""
-                
-                Just _ ->
-                    Debug.todo "branch 'Just _' not implemented"
-        
-        _ ->
-            ""
-    `;
-
-    await testCodeAction(
-      source,
-      [{ title: "Add missing case branches" }],
-      expectedSource,
-    );
-  });
-});
diff --git a/test/codeActionTests/codeActionTestBase.ts b/test/codeActionTests/codeActionTestBase.ts
index 2be2e88..8ca116e 100644
--- a/test/codeActionTests/codeActionTestBase.ts
+++ b/test/codeActionTests/codeActionTestBase.ts
@@ -80,8 +80,6 @@ export async function testCodeAction(
 
   const testUri = URI.file(baseUri + "Test.elm").toString();
 
-  result.sources["Test.elm"] = stripCommentLines(result.sources["Test.elm"]);
-
   const program = await treeParser.getProgram(result.sources);
   const sourceFile = program.getForest().getByUri(testUri);
 
@@ -132,7 +130,8 @@ export async function testCodeAction(
       expect(
         applyEditsToSource(
           stripCommentLines(result.sources[uri]),
-          codeActions[0].edit!.changes![URI.file(baseUri + uri).toString()],
+          codeActions[0].edit?.changes![URI.file(baseUri + uri).toString()] ??
+            [],
         ),
       ).toEqual(source);
     });
diff --git a/test/completionProvider.test.ts b/test/completionProvider.test.ts
index b942f4f..79e9206 100644
--- a/test/completionProvider.test.ts
+++ b/test/completionProvider.test.ts
@@ -1503,83 +1503,4 @@ func model =
 
     await testCompletions(source, ["details"]);
   });
-
-  it("Completions for module alias if using an import alias", async () => {
-    const source = `
---@ Module.elm
-module Module exposing (..)
-
-foo = ""
-
-type Maybe a = Just a | Nothing
-
---@ Test.elm
-module Test exposing (..)
-
-import Module as M
-
-func =
-    M.f{-caret-}
-`;
-
-    await testCompletions(
-      source,
-      ["foo", "Maybe", "Just", "Nothing"],
-      "exactMatch",
-    );
-  });
-
-  it("No completions for module if using an import alias", async () => {
-    const source = `
---@ Module.elm
-module Module exposing (..)
-
-foo = ""
-
-type Maybe a = Just a | Nothing
-
---@ Test.elm
-module Test exposing (..)
-
-import Module as M
-
-func =
-    Module.f{-caret-}
-`;
-
-    await testCompletions(source, [], "exactMatch");
-  });
-
-  it("Multiple modules with the same name/alias should have all completions", async () => {
-    const source = `
---@ Module.elm
-module Module exposing (..)
-
-foo = ""
-
-type Maybe a = Just a | Nothing
-
---@ OtherModule.elm
-module OtherModule exposing (..)
-
-bar = ""
-
-type Result e a = Ok a | Err e
-
---@ Test.elm
-module Test exposing (..)
-
-import Module as M
-import OtherModule as M
-
-func =
-    M.f{-caret-}
-`;
-
-    await testCompletions(
-      source,
-      ["foo", "Maybe", "Just", "Nothing", "bar", "Result", "Ok", "Err"],
-      "exactMatch",
-    );
-  });
 });
diff --git a/test/diagnosticTests/elmDiagnostics.test.ts b/test/diagnosticTests/elmDiagnostics.test.ts
index e6ff371..fef0129 100644
--- a/test/diagnosticTests/elmDiagnostics.test.ts
+++ b/test/diagnosticTests/elmDiagnostics.test.ts
@@ -1407,7 +1407,7 @@ func result =
     );
   });
 
-  test("test case patterns should not have an error - multiple cons", async () => {
+  xtest("test missing case patterns should not have an error - multiple cons", async () => {
     const source = `
 --@ Test.elm
 module Test exposing (..)
diff --git a/test/referencesProviderTests/functionReferences.test.ts b/test/referencesProviderTests/functionReferences.test.ts
index 39585ee..afcb5ec 100644
--- a/test/referencesProviderTests/functionReferences.test.ts
+++ b/test/referencesProviderTests/functionReferences.test.ts
@@ -5,7 +5,6 @@ describe("functionReferences", () => {
 
   it(`function references in other files`, async () => {
     const source = `
-
 --@ Module.elm
 module Module exposing (foo)
                        --X
@@ -35,7 +34,6 @@ func = foo
 
   it(`function references used with module prefix in other files`, async () => {
     const source = `
-
 --@ Module.elm
 module Module exposing (foo)
                        --X
@@ -63,7 +61,6 @@ func = Module.foo
 
   it(`function references used with module alias prefix in other files`, async () => {
     const source = `
-
 --@ Module.elm
 module Module exposing (foo)
                        --X
@@ -91,7 +88,6 @@ func = Mod.foo
 
   it(`local calls to a function`, async () => {
     const source = `
-
 --@ Module.elm
 module Module exposing (foo)
                         --X
@@ -106,12 +102,59 @@ bar = foo
 
   it(`function annotation gets a reference`, async () => {
     const source = `
-
 --@ Module.elm
 foo : Int
 --X
 foo = 42
 --^
+`;
+    await testBase.testReferences(source);
+  });
+
+  it(`let function should not be referenced outside of let`, async () => {
+    const source = `
+--@ Module.elm
+foo =
+    let
+        func = ""
+       --^
+        
+        bar = func
+              --X
+
+        val = ""
+    in
+    ""
+
+test = func
+`;
+    await testBase.testReferences(source);
+  });
+
+  it(`function should be referenced if used as a base record`, async () => {
+    const source = `
+--@ Module.elm
+foo =
+--^
+    { field : String }
+
+test = 
+    { foo | field = "" }
+     --X
+`;
+    await testBase.testReferences(source);
+  });
+
+  it(`function should be referenced if used as a record accessor`, async () => {
+    const source = `
+--@ Module.elm
+foo =
+--^
+    { field : String }
+
+test = 
+    foo.field
+   --X
 `;
     await testBase.testReferences(source);
   });
diff --git a/test/referencesProviderTests/patternReferences.test.ts b/test/referencesProviderTests/patternReferences.test.ts
new file mode 100644
index 0000000..09fb104
--- /dev/null
+++ b/test/referencesProviderTests/patternReferences.test.ts
@@ -0,0 +1,27 @@
+import { ReferencesProviderTestBase } from "./referencesProviderTestBase";
+
+describe("functionReferences", () => {
+  const testBase = new ReferencesProviderTestBase();
+
+  it(`let destructured patterns should have references`, async () => {
+    const source = `
+--@ Module.elm
+module Module exposing (foo)
+                       
+foo =
+    let
+        ( first, second ) = func
+          --^
+    in
+    case first of
+         --X
+        "" ->
+            bar first
+                --X
+
+        _ ->
+            ""
+`;
+    await testBase.testReferences(source);
+  });
+});
diff --git a/test/referencesProviderTests/referencesProviderTestBase.ts b/test/referencesProviderTests/referencesProviderTestBase.ts
index 8732d2a..64e2abd 100644
--- a/test/referencesProviderTests/referencesProviderTestBase.ts
+++ b/test/referencesProviderTests/referencesProviderTestBase.ts
@@ -56,6 +56,16 @@ export class ReferencesProviderTestBase {
       referencePosition: referenceTest.invokePosition,
     });
 
+    if (references.length !== referenceTest.references.length) {
+      console.log(
+        `Expected\n${JSON.stringify(
+          references,
+          null,
+          2,
+        )}\nto equal\n${JSON.stringify(referenceTest.references, null, 2)}`,
+      );
+    }
+
     expect(references.length).toEqual(referenceTest.references.length);
 
     referenceTest.references.forEach(({ referencePosition, referenceFile }) => {
@@ -77,6 +87,9 @@ export class ReferencesProviderTestBase {
       if (!foundReference) {
         console.log(referenceUri);
         console.log(referencePosition);
+        console.log(
+          `Missing reference in ${JSON.stringify(references, null, 2)}`,
+        );
       }
 
       expect(foundReference).toBeTruthy();
diff --git a/test/referencesProviderTests/typeReferences.test.ts b/test/referencesProviderTests/typeReferences.test.ts
new file mode 100644
index 0000000..58fd027
--- /dev/null
+++ b/test/referencesProviderTests/typeReferences.test.ts
@@ -0,0 +1,133 @@
+import { ReferencesProviderTestBase } from "./referencesProviderTestBase";
+
+describe("type references", () => {
+  const testBase = new ReferencesProviderTestBase();
+
+  it(`type references in other files`, async () => {
+    const source = `
+--@ Module.elm
+module Module exposing (MyType(..))
+                        --X
+type MyType = A | B
+     --^
+
+--@ Bar.elm
+module Bar exposing (..)
+
+import Module exposing (MyType(..))
+                        --X
+bar : MyType
+      --X
+bar = A
+
+--@ FooExtra.elm
+module FooExtra exposing (..)
+
+import Module exposing (MyType(..))
+                        --X
+func : String -> MyType
+                 --X
+func a = B
+`;
+    await testBase.testReferences(source);
+  });
+
+  xit(`type references in other files used with module prefix`, async () => {
+    const source = `
+--@ Module.elm
+module Module exposing (MyType(..))
+                        --X
+type MyType = A | B
+     --^
+
+--@ Bar.elm
+module Bar exposing (..)
+
+import Module 
+
+bar : Module.MyType
+             --X
+bar = A
+
+--@ FooExtra.elm
+module FooExtra exposing (..)
+
+import Module as M
+
+func : String -> M.MyType
+                   --X
+func a = B
+`;
+    await testBase.testReferences(source);
+  });
+
+  it(`union constructor references in other files`, async () => {
+    const source = `
+--@ Module.elm
+module Module exposing (MyType(..))
+
+type MyType = A | B
+            --^
+
+--@ Bar.elm
+module Bar exposing (..)
+
+import Module exposing (MyType(..))
+
+bar : MyType
+bar = A
+    --X
+
+--@ FooExtra.elm
+module FooExtra exposing (..)
+
+import Module exposing (MyType(..))
+
+func : MyType -> String
+func a = 
+    case a of
+        B ->
+          ""
+
+        A ->
+      --X
+          ""
+`;
+    await testBase.testReferences(source);
+  });
+
+  it(`union constructor references in other files using module prefix`, async () => {
+    const source = `
+--@ Module.elm
+module Module exposing (MyType(..))
+
+type MyType = A | B
+            --^
+
+--@ Bar.elm
+module Bar exposing (..)
+
+import Module
+
+bar : MyType
+bar = Module.A
+        --X
+
+--@ FooExtra.elm
+module FooExtra exposing (..)
+
+import Module as M
+
+func : MyType -> String
+func a = 
+    case a of
+        M.B ->
+          ""
+
+        M.A ->
+      --X
+          ""
+`;
+    await testBase.testReferences(source);
+  });
+});
diff --git a/test/renameProvider.test.ts b/test/renameProvider.test.ts
index 7789631..17924a1 100644
--- a/test/renameProvider.test.ts
+++ b/test/renameProvider.test.ts
@@ -130,7 +130,7 @@ func = Module.App.foo
 --@ Module/App.elm
 module Module.App exposing (foo)
 
-foo = ""
+foo = ""		
 `;
 
     const expectedResult = `
@@ -144,7 +144,7 @@ func = Module.App.bar
 --@ Module/App.elm
 module Module.App exposing (bar)
 
-bar = ""
+bar = ""		
 `;
 
     const renameRange = Range.create(
@@ -211,118 +211,4 @@ foo = ""
     await testPrepareRename(source2, renameRange);
     await testRename(source2, "Module.NewApp", expectedResult);
   });
-
-  it("renaming a type alias", async () => {
-    const source = `
---@ Test.elm
-module Test exposing (Type, t)
-
-type alias Type =
-    { tag : String
-    , data : Int
-    }
-
-t : Type
-  --^
-t =
-    {}
-
---@ Module/App.elm
-module Module.App exposing (foo)
-
-import Test exposing (Type)
-
-foo : Type
-foo = {}
-`;
-
-    const expectedResult = `
---@ Test.elm
-module Test exposing (NewType, t)
-
-type alias NewType =
-    { tag : String
-    , data : Int
-    }
-
-t : NewType
-t =
-    {}
-
---@ Module/App.elm
-module Module.App exposing (foo)
-
-import Test exposing (NewType)
-
-foo : NewType
-foo = {}
-    `;
-
-    const renameRange = Range.create(
-      Position.create(7, 4),
-      Position.create(7, 8),
-    );
-
-    await testPrepareRename(source, renameRange);
-    await testRename(source, "NewType", expectedResult);
-  });
-
-  it("renaming a type union constructor", async () => {
-    const source = `
---@ Test.elm
-module Test exposing (State(..), t)
-
-type State
-    = Ok
-    | Average
-    | Bad
-
-t : State
-t =
-    Ok
-  --^
-
---@ Module/App.elm
-module Module.App exposing (foo)
-
-import Test exposing (State(..))
-
-
-foo : State
-foo =
-    Ok
-`;
-
-    const expectedResult = `
---@ Test.elm
-module Test exposing (State(..), t)
-
-type State
-    = NotOkay
-    | Average
-    | Bad
-
-t : State
-t =
-    NotOkay
-
---@ Module/App.elm
-module Module.App exposing (foo)
-
-import Test exposing (State(..))
-
-
-foo : State
-foo =
-    NotOkay
-    `;
-
-    const renameRange = Range.create(
-      Position.create(9, 4),
-      Position.create(9, 6),
-    );
-
-    await testPrepareRename(source, renameRange);
-    await testRename(source, "NotOkay", expectedResult);
-  });
 });