Repository: elm-tooling/elm-language-server
Pull request #725 (2022-07-16 07:49:18)

Add exposing type with variants action
Currently, expose/unexpose action does not cover exposing types with variants, but I want that capability.

This PR implements it.


Patch:
diff --git a/src/providers/codeAction/exposeUnexposeCodeAction.ts b/src/providers/codeAction/exposeUnexposeCodeAction.ts
index f2384e3..132a584 100644
--- a/src/providers/codeAction/exposeUnexposeCodeAction.ts
+++ b/src/providers/codeAction/exposeUnexposeCodeAction.ts
@@ -87,6 +87,19 @@ CodeActionProvider.registerRefactorAction(refactorName, {
             range: params.range,
           },
         });
+
+        if (nodeAtPosition.parent?.type === "type_declaration") {
+          result.push({
+            title: `Expose Type with Variants`,
+            kind: CodeActionKind.Refactor,
+            data: {
+              actionName: "expose_type_with_variants",
+              refactorName,
+              uri: params.sourceFile.uri,
+              range: params.range,
+            },
+          });
+        }
       }
     }
 
@@ -113,10 +126,12 @@ CodeActionProvider.registerRefactorAction(refactorName, {
         return edit ? { edits: [edit] } : {};
       }
       case "expose_function":
-      case "expose_type": {
+      case "expose_type":
+      case "expose_type_with_variants": {
         const edit = RefactorEditUtils.exposeValueInModule(
           tree,
           nodeAtPosition.text,
+          actionName === "expose_type_with_variants",
         );
         return edit ? { edits: [edit] } : {};
       }
diff --git a/src/util/refactorEditUtils.ts b/src/util/refactorEditUtils.ts
index 1672158..080819b 100644
--- a/src/util/refactorEditUtils.ts
+++ b/src/util/refactorEditUtils.ts
@@ -105,12 +105,17 @@ export class RefactorEditUtils {
   public static exposeValueInModule(
     tree: Tree,
     valueName: string,
+    withVariants = false,
   ): TextEdit | undefined {
     const exposedNodes = TreeUtils.getModuleExposingListNodes(tree);
 
     if (exposedNodes.length > 0) {
       const lastExposedNode = exposedNodes[exposedNodes.length - 1];
 
+      if (withVariants) {
+        valueName += "(..)";
+      }
+
       if (lastExposedNode) {
         return TextEdit.insert(
           Position.create(


Test patch:
diff --git a/test/codeActionTests/exposeUnexposeCodeAction.test.ts b/test/codeActionTests/exposeUnexposeCodeAction.test.ts
index 1a299cb..ced3d8a 100644
--- a/test/codeActionTests/exposeUnexposeCodeAction.test.ts
+++ b/test/codeActionTests/exposeUnexposeCodeAction.test.ts
@@ -70,4 +70,105 @@ world =
       expectedSource,
     );
   })
+
+  test("exposing a type is available", async () => {
+    const source = `
+--@ Test.elm
+module Test exposing (hello)
+
+hello : string
+hello =
+    "hello"
+
+type World =
+   --^
+    World
+`;
+
+    const expectedSource = `
+--@ Test.elm
+module Test exposing (hello, World)
+
+hello : string
+hello =
+    "hello"
+
+type World =
+    World
+`;
+
+    await testCodeAction(
+      source,
+      [{ title: `Expose Type` }],
+      expectedSource,
+    );
+  })
+
+  test("unexposing a type is available", async () => {
+    const source = `
+--@ Test.elm
+module Test exposing (hello, World)
+
+hello : string
+hello =
+    "hello"
+
+type World =
+   --^
+    World
+`;
+
+    const expectedSource = `
+--@ Test.elm
+module Test exposing (hello)
+
+hello : string
+hello =
+    "hello"
+
+type World =
+    World
+`;
+
+    await testCodeAction(
+      source,
+      [{ title: `Unexpose Type` }],
+      expectedSource,
+    );
+  })
+
+  test("exposing a type with all variants is available", async () => {
+    const source = `
+--@ Test.elm
+module Test exposing (hello)
+
+hello : string
+hello =
+    "hello"
+
+type Hoge
+   --^
+    = Hello
+    | World
+`;
+
+    const expectedSource = `
+--@ Test.elm
+module Test exposing (hello, Hoge(..))
+
+hello : string
+hello =
+    "hello"
+
+type Hoge
+    = Hello
+    | World
+`;
+
+    await testCodeAction(
+      source,
+      [{ title: `Expose Type with Variants` }],
+      expectedSource,
+    );
+  })
 })