Repository: elm-tooling/elm-language-server
Pull request #833 (2022-11-14 23:00:55)

Bump @typescript-eslint/parser from 5.42.1 to 5.43.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.42.1 to 5.43.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/typescript-eslint/typescript-eslint/releases"><code>@​typescript-eslint/parser</code>'s releases</a>.</em></p>
<blockquote>
<h2>v5.43.0</h2>
<h1><a href="https://github.com/typescript-eslint/typescript-eslint/compare/v5.42.1...v5.43.0">5.43.0</a> (2022-11-14)</h1>
<h3>Bug Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-shadow] handle false positives on generics and parameters (<a href="https://github-redirect.dependabot.com/typescript-eslint/typescript-eslint/issues/5902">#5902</a>) (<a href="https://github.com/typescript-eslint/typescript-eslint/commit/769e8c8b9a51cd3448e47d13c7b0dab0468ee23c">769e8c8</a>)</li>
<li><strong>eslint-plugin:</strong> [promise-function-async] handle keyword token (<a href="https://github-redirect.dependabot.com/typescript-eslint/typescript-eslint/issues/5907">#5907</a>) (<a href="https://github.com/typescript-eslint/typescript-eslint/commit/f25a94fa75e497a6b9ec29a008bcc89818eed60d">f25a94f</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>eslint-plugin:</strong> [consistent-type-imports] support fixing to inline types (<a href="https://github-redirect.dependabot.com/typescript-eslint/typescript-eslint/issues/5050">#5050</a>) (<a href="https://github.com/typescript-eslint/typescript-eslint/commit/75dcdf164d206c5530ba7cc095c4599ec90abe35">75dcdf1</a>)</li>
<li><strong>eslint-plugin:</strong> [naming-convention] add support for &quot;override&quot; and &quot;async&quot; modifiers (<a href="https://github-redirect.dependabot.com/typescript-eslint/typescript-eslint/issues/5310">#5310</a>) (<a href="https://github-redirect.dependabot.com/typescript-eslint/typescript-eslint/issues/5610">#5610</a>) (<a href="https://github.com/typescript-eslint/typescript-eslint/commit/c759da169390ba490eee9ef773cc9edc88a32817">c759da1</a>)</li>
<li><strong>eslint-plugin:</strong> [prefer-optional-chain] support suggesting <code>!foo || !foo.bar</code> as a valid match for the rule (<a href="https://github-redirect.dependabot.com/typescript-eslint/typescript-eslint/issues/5594">#5594</a>) (<a href="https://github.com/typescript-eslint/typescript-eslint/commit/923d486c8c9c9096deac425e7a6cb0b6457eacbd">923d486</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md"><code>@​typescript-eslint/parser</code>'s changelog</a>.</em></p>
<blockquote>
<h1><a href="https://github.com/typescript-eslint/typescript-eslint/compare/v5.42.1...v5.43.0">5.43.0</a> (2022-11-14)</h1>
<p><strong>Note:</strong> Version bump only for package <code>@​typescript-eslint/parser</code></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/typescript-eslint/typescript-eslint/commit/8af1b4d970438b27ea041717bddadc41af8fc72a"><code>8af1b4d</code></a> chore: publish v5.43.0</li>
<li>See full diff in <a href="https://github.com/typescript-eslint/typescript-eslint/commits/v5.43.0/packages/parser">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@typescript-eslint/parser&package-manager=npm_and_yarn&previous-version=5.42.1&new-version=5.43.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/package-lock.json b/package-lock.json
index 2e3116c..810c073 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1423,14 +1423,14 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "5.42.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz",
-      "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==",
+      "version": "5.43.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz",
+      "integrity": "sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.42.1",
-        "@typescript-eslint/types": "5.42.1",
-        "@typescript-eslint/typescript-estree": "5.42.1",
+        "@typescript-eslint/scope-manager": "5.43.0",
+        "@typescript-eslint/types": "5.43.0",
+        "@typescript-eslint/typescript-estree": "5.43.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -1450,13 +1450,13 @@
       }
     },
     "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.42.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz",
-      "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==",
+      "version": "5.43.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz",
+      "integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.42.1",
-        "@typescript-eslint/visitor-keys": "5.42.1"
+        "@typescript-eslint/types": "5.43.0",
+        "@typescript-eslint/visitor-keys": "5.43.0"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1467,9 +1467,9 @@
       }
     },
     "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
-      "version": "5.42.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz",
-      "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==",
+      "version": "5.43.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz",
+      "integrity": "sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1480,13 +1480,13 @@
       }
     },
     "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.42.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz",
-      "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==",
+      "version": "5.43.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz",
+      "integrity": "sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.42.1",
-        "@typescript-eslint/visitor-keys": "5.42.1",
+        "@typescript-eslint/types": "5.43.0",
+        "@typescript-eslint/visitor-keys": "5.43.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -1507,12 +1507,12 @@
       }
     },
     "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.42.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz",
-      "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==",
+      "version": "5.43.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz",
+      "integrity": "sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.42.1",
+        "@typescript-eslint/types": "5.43.0",
         "eslint-visitor-keys": "^3.3.0"
       },
       "engines": {
@@ -2462,9 +2462,9 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.27.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz",
-      "integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==",
+      "version": "8.28.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz",
+      "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==",
       "dev": true,
       "dependencies": {
         "@eslint/eslintrc": "^1.3.3",
@@ -7880,41 +7880,41 @@
       }
     },
     "@typescript-eslint/parser": {
-      "version": "5.42.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz",
-      "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==",
+      "version": "5.43.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz",
+      "integrity": "sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "5.42.1",
-        "@typescript-eslint/types": "5.42.1",
-        "@typescript-eslint/typescript-estree": "5.42.1",
+        "@typescript-eslint/scope-manager": "5.43.0",
+        "@typescript-eslint/types": "5.43.0",
+        "@typescript-eslint/typescript-estree": "5.43.0",
         "debug": "^4.3.4"
       },
       "dependencies": {
         "@typescript-eslint/scope-manager": {
-          "version": "5.42.1",
-          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz",
-          "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==",
+          "version": "5.43.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz",
+          "integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==",
           "dev": true,
           "requires": {
-            "@typescript-eslint/types": "5.42.1",
-            "@typescript-eslint/visitor-keys": "5.42.1"
+            "@typescript-eslint/types": "5.43.0",
+            "@typescript-eslint/visitor-keys": "5.43.0"
           }
         },
         "@typescript-eslint/types": {
-          "version": "5.42.1",
-          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz",
-          "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==",
+          "version": "5.43.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz",
+          "integrity": "sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==",
           "dev": true
         },
         "@typescript-eslint/typescript-estree": {
-          "version": "5.42.1",
-          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz",
-          "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==",
+          "version": "5.43.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz",
+          "integrity": "sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==",
           "dev": true,
           "requires": {
-            "@typescript-eslint/types": "5.42.1",
-            "@typescript-eslint/visitor-keys": "5.42.1",
+            "@typescript-eslint/types": "5.43.0",
+            "@typescript-eslint/visitor-keys": "5.43.0",
             "debug": "^4.3.4",
             "globby": "^11.1.0",
             "is-glob": "^4.0.3",
@@ -7923,12 +7923,12 @@
           }
         },
         "@typescript-eslint/visitor-keys": {
-          "version": "5.42.1",
-          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz",
-          "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==",
+          "version": "5.43.0",
+          "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz",
+          "integrity": "sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==",
           "dev": true,
           "requires": {
-            "@typescript-eslint/types": "5.42.1",
+            "@typescript-eslint/types": "5.43.0",
             "eslint-visitor-keys": "^3.3.0"
           }
         }
@@ -8592,9 +8592,9 @@
       "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
     },
     "eslint": {
-      "version": "8.27.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz",
-      "integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==",
+      "version": "8.28.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz",
+      "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==",
       "dev": true,
       "requires": {
         "@eslint/eslintrc": "^1.3.3",
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index fc5cd63..9ac4032 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -94,7 +94,6 @@ export interface IProgram {
   getTypeChecker(): TypeChecker;
   markAsDirty(): void;
   getPossibleImportsCache(): IPossibleImportsCache;
-  getOperatorsCache(): Map<string, DefinitionResult>;
   getSemanticDiagnostics(
     sourceFile: ISourceFile,
     cancellationToken?: ICancellationToken,
@@ -151,7 +150,6 @@ export class Program implements IProgram {
   private typeChecker: TypeChecker | undefined;
   private dirty = true;
   private possibleImportsCache: IPossibleImportsCache;
-  private operatorsCache: Map<string, DefinitionResult>;
   private diagnosticsCache: Map<string, Diagnostic[]>;
   private rootProject!: ElmProject;
   private forest!: IForest;
@@ -170,7 +168,6 @@ export class Program implements IProgram {
 
     this.typeCache = new TypeCache();
     this.possibleImportsCache = new PossibleImportsCache();
-    this.operatorsCache = new Map<string, DefinitionResult>();
     this.diagnosticsCache = new Map<string, Diagnostic[]>();
     this.host = programHost ?? createNodeProgramHost();
   }
@@ -255,10 +252,6 @@ export class Program implements IProgram {
     return this.possibleImportsCache;
   }
 
-  public getOperatorsCache(): Map<string, DefinitionResult> {
-    return this.operatorsCache;
-  }
-
   public getSemanticDiagnostics(
     sourceFile: ISourceFile,
     cancellationToken?: ICancellationToken,
diff --git a/src/compiler/typeChecker.ts b/src/compiler/typeChecker.ts
index ab55ab9..0767787 100644
--- a/src/compiler/typeChecker.ts
+++ b/src/compiler/typeChecker.ts
@@ -683,12 +683,6 @@ export function createTypeChecker(program: IProgram): TypeChecker {
         };
       }
     } else if (nodeAtPosition.type === "operator_identifier") {
-      const operatorsCache = program.getOperatorsCache();
-      const cached = operatorsCache.get(nodeText);
-      if (cached) {
-        return cached;
-      }
-
       const definitionNode = TreeUtils.findOperator(sourceFile, nodeText);
       if (definitionNode) {
         const result: DefinitionResult = {
@@ -699,7 +693,6 @@ export function createTypeChecker(program: IProgram): TypeChecker {
           },
           diagnostics: [],
         };
-        operatorsCache.set(nodeText, Object.freeze(result));
         return result;
       } else {
         const operatorImport = findImport(sourceFile, nodeText, "Var")[0];
@@ -709,7 +702,6 @@ export function createTypeChecker(program: IProgram): TypeChecker {
             symbol: operatorImport,
             diagnostics: [],
           };
-          operatorsCache.set(nodeText, Object.freeze(result));
           return result;
         }
       }
diff --git a/src/providers/completionProvider.ts b/src/providers/completionProvider.ts
index 37ae5c0..44da1e8 100644
--- a/src/providers/completionProvider.ts
+++ b/src/providers/completionProvider.ts
@@ -45,6 +45,8 @@ interface ICompletionOptions {
   detail?: string;
   additionalTextEdits?: TextEdit[];
   filterText?: string;
+  labelDescription?: string;
+  labelDetail?: string;
 }
 
 export class CompletionProvider {
@@ -565,6 +567,7 @@ export class CompletionProvider {
       }
 
       const label = element.name;
+      const labelDescription = element.fromModule.name;
       let filterText = label;
 
       const dotIndex = label.lastIndexOf(".");
@@ -599,6 +602,7 @@ export class CompletionProvider {
               range,
               sortPrefix,
               filterText,
+              labelDescription,
             }),
           );
           break;
@@ -609,6 +613,7 @@ export class CompletionProvider {
               range,
               sortPrefix,
               filterText,
+              labelDescription,
             }),
           );
           break;
@@ -619,6 +624,7 @@ export class CompletionProvider {
               label,
               range,
               sortPrefix,
+              labelDescription,
             }),
           );
           break;
@@ -630,6 +636,7 @@ export class CompletionProvider {
               range,
               sortPrefix,
               filterText,
+              labelDescription,
             }),
           );
           break;
@@ -641,6 +648,7 @@ export class CompletionProvider {
               range,
               sortPrefix,
               filterText,
+              labelDescription,
             }),
           );
           break;
@@ -830,7 +838,7 @@ export class CompletionProvider {
     targetNode: SyntaxNode,
     replaceRange: Range,
   ): CompletionItem[] {
-    const result = [];
+    const result: CompletionItem[] = [];
     const foundType = checker.findType(targetNode);
 
     if (foundType.nodeType === "Record") {
@@ -923,6 +931,10 @@ export class CompletionProvider {
       detail: options.detail,
       additionalTextEdits: options.additionalTextEdits,
       filterText: options.filterText,
+      labelDetails: {
+        description: options.labelDescription,
+        detail: options.labelDetail,
+      },
     };
   }
 
@@ -987,7 +999,10 @@ export class CompletionProvider {
         );
       }
 
-      if (symbol.type === "FunctionParameter") {
+      if (
+        symbol.type === "FunctionParameter" ||
+        symbol.type === "AnonymousFunctionParameter"
+      ) {
         const markdownDocumentation =
           HintHelper.createHintFromFunctionParameter(symbol.node);
         result.push(
@@ -1019,19 +1034,6 @@ export class CompletionProvider {
           }
         }
       }
-
-      if (symbol.type === "AnonymousFunctionParameter") {
-        const markdownDocumentation =
-          HintHelper.createHintFromFunctionParameter(symbol.node);
-        result.push(
-          this.createVariableCompletion({
-            markdownDocumentation,
-            label: symbol.name,
-            range,
-            sortPrefix,
-          }),
-        );
-      }
     });
 
     return result;
@@ -1143,13 +1145,14 @@ export class CompletionProvider {
 
       const sortText = i < 10 ? `0${i}` : i;
 
-      const completionOptions = {
+      const completionOptions: ICompletionOptions = {
         markdownDocumentation,
         label: possibleImport.value,
         range,
         sortPrefix: `f${sortText}`,
         detail,
         additionalTextEdits: importTextEdit ? [importTextEdit] : undefined,
+        labelDescription: possibleImport.module,
       };
       if (possibleImport.type === "Function") {
         result.push(this.createFunctionCompletion(completionOptions));
@@ -1165,6 +1168,7 @@ export class CompletionProvider {
             sortPrefix: `f${i}`,
             detail,
             additionalTextEdits: importTextEdit ? [importTextEdit] : undefined,
+            labelDescription: possibleImport.module,
           }),
         );
       }


Test patch:
diff --git a/test/diagnosticTests/elmDiagnostics.test.ts b/test/diagnosticTests/elmDiagnostics.test.ts
index 7f0590b..6675c4e 100644
--- a/test/diagnosticTests/elmDiagnostics.test.ts
+++ b/test/diagnosticTests/elmDiagnostics.test.ts
@@ -18,69 +18,12 @@ import { SourceTreeParser, srcUri } from "../utils/sourceTreeParser";
 import { diff } from "jest-diff";
 import path from "path";
 import { describe, expect } from "@jest/globals";
-
-const basicsSources = `
---@ Basics.elm
-module Basics exposing ((+), (|>), (>>), (==), (>), (++), Int, Float, Bool(..), Order(..), negate)
-
-infix left  0 (|>) = apR
-infix non   4 (==) = eq
-infix right 5 (++) = append
-infix left  6 (+)  = add
-infix right 9 (>>) = composeR
-infix non   4 (>)  = gt
-
-type Int = Int
-
-type Float = Float
-
-type Bool = True | False
-
-add : number -> number -> number
-add =
-  Elm.Kernel.Basics.add
-
-apR : a -> (a -> b) -> b
-apR x f =
-  f x
-
-eq : a -> a -> Bool
-eq =
-  Elm.Kernel.Utils.equal
-
-composeR : (a -> b) -> (b -> c) -> (a -> c)
-composeR f g x =
-  g (f x)
-
-gt : comparable -> comparable -> Bool
-gt =
-  Elm.Kernel.Utils.gt
-
-type Order = LT | EQ | GT
-
-negate : number -> number
-negate n =
-  -n
-
-append : appendable -> appendable -> appendable
-append =
-  Elm.Kernel.Utils.append
-`;
-
-const stringSources = `
---@ String.elm
-module String exposing (String, fromInt, fromFloat)
-
-type String = String
-
-fromInt : Int -> String
-fromInt =
-  \\_ -> ""
-
-fromFloat : Float -> String
-fromFloat =
-  \\_ -> ""
-`;
+import {
+  basicsSources,
+  listSources,
+  parserSources,
+  stringSources,
+} from "./sources";
 
 describe("test elm diagnostics", () => {
   const treeParser = new SourceTreeParser();
@@ -114,8 +57,18 @@ describe("test elm diagnostics", () => {
 
     const diagnostics: Diagnostic[] = [];
 
+    const coreModules = [
+      "Basics",
+      "List",
+      "Parser",
+      "Parser.Advanced",
+      "String",
+      "Set",
+      "Dict",
+      "Char",
+    ];
     program.getForest().treeMap.forEach((sourceFile) => {
-      if (!sourceFile.uri.includes("Basic")) {
+      if (!coreModules.find((module) => sourceFile.uri.includes(module))) {
         diagnostics.push(...program.getSyntacticDiagnostics(sourceFile));
         diagnostics.push(...program.getSemanticDiagnostics(sourceFile));
 
@@ -1587,4 +1540,51 @@ foo asInt myNumber =
       { message: Diagnostics.TypeMismatch, args: ["Float", "Int"] },
     ]);
   });
+
+  it.only("operators from different files should not have an errors", async () => {
+    const source = `
+--@ Other.elm
+module Other exposing (foo)
+
+import Parser exposing ((|.), (|=), Parser)
+
+foo : number
+foo =
+    3
+
+
+oneOrMore : Parser a -> Parser (List a)
+oneOrMore parser =
+    Parser.andThen
+        (\\firstValue ->
+            Parser.loop [ firstValue ]
+                (\\reversedValues ->
+                    Parser.oneOf
+                        [ Parser.succeed (Parser.Done (List.reverse reversedValues))
+                            |. Parser.end
+                        , Parser.succeed (\\nextValue -> Parser.Loop (nextValue :: reversedValues))
+                            |= parser
+                        , Parser.succeed (Parser.Done (List.reverse reversedValues))
+                        ]
+                )
+        )
+        parser
+
+        
+--@ Test.elm
+module Test exposing (..)
+
+import Parser.Advanced as Parser exposing ((|.), (|=))
+
+test : Parser.Parser Never () ()
+test =
+    Parser.succeed (\\_ -> ())
+        |= Parser.getOffset  
+`;
+
+    await testTypeInference(
+      basicsSources + listSources + stringSources + parserSources + source,
+      [],
+    );
+  });
 });
diff --git a/test/diagnosticTests/sources.ts b/test/diagnosticTests/sources.ts
new file mode 100644
index 0000000..3341347
--- /dev/null
+++ b/test/diagnosticTests/sources.ts
@@ -0,0 +1,1936 @@
+export const basicsSources = `
+--@ Basics.elm
+module Basics exposing
+  ( Int, Float
+  , (+), (-), (*), (/), (//), (^)
+  , toFloat, round, floor, ceiling, truncate
+  , (==), (/=)
+  , (<), (>), (<=), (>=), max, min, compare, Order(..)
+  , Bool(..), not, (&&), (||), xor
+  , (++)
+  , modBy, remainderBy, negate, abs, clamp, sqrt, logBase, e
+  , pi, cos, sin, tan, acos, asin, atan, atan2
+  , degrees, radians, turns
+  , toPolar, fromPolar
+  , isNaN, isInfinite
+  , identity, always, (<|), (|>), (<<), (>>), Never, never
+  )
+
+
+import Elm.Kernel.Basics
+import Elm.Kernel.Utils
+
+
+
+-- INFIX OPERATORS
+
+
+infix right 0 (<|) = apL
+infix left  0 (|>) = apR
+infix right 2 (||) = or
+infix right 3 (&&) = and
+infix non   4 (==) = eq
+infix non   4 (/=) = neq
+infix non   4 (<)  = lt
+infix non   4 (>)  = gt
+infix non   4 (<=) = le
+infix non   4 (>=) = ge
+infix right 5 (++) = append
+infix left  6 (+)  = add
+infix left  6 (-)  = sub
+infix left  7 (*)  = mul
+infix left  7 (/)  = fdiv
+infix left  7 (//) = idiv
+infix right 8 (^)  = pow
+infix left  9 (<<) = composeL
+infix right 9 (>>) = composeR
+
+
+
+-- MATHEMATICS
+
+type Int = Int -- NOTE: The compiler provides the real implementation.
+
+
+type Float = Float -- NOTE: The compiler provides the real implementation.
+
+
+add : number -> number -> number
+add =
+  Elm.Kernel.Basics.add
+
+
+sub : number -> number -> number
+sub =
+  Elm.Kernel.Basics.sub
+
+
+mul : number -> number -> number
+mul =
+  Elm.Kernel.Basics.mul
+
+
+fdiv : Float -> Float -> Float
+fdiv =
+  Elm.Kernel.Basics.fdiv
+
+
+idiv : Int -> Int -> Int
+idiv =
+  Elm.Kernel.Basics.idiv
+
+
+pow : number -> number -> number
+pow =
+  Elm.Kernel.Basics.pow
+
+
+
+-- INT TO FLOAT / FLOAT TO INT
+
+
+toFloat : Int -> Float
+toFloat =
+  Elm.Kernel.Basics.toFloat
+
+
+round : Float -> Int
+round =
+  Elm.Kernel.Basics.round
+
+
+floor : Float -> Int
+floor =
+  Elm.Kernel.Basics.floor
+
+
+ceiling : Float -> Int
+ceiling =
+  Elm.Kernel.Basics.ceiling
+
+
+truncate : Float -> Int
+truncate =
+  Elm.Kernel.Basics.truncate
+
+
+
+-- EQUALITY
+
+
+eq : a -> a -> Bool
+eq =
+  Elm.Kernel.Utils.equal
+
+
+neq : a -> a -> Bool
+neq =
+  Elm.Kernel.Utils.notEqual
+
+
+
+-- COMPARISONS
+
+
+lt : comparable -> comparable -> Bool
+lt =
+  Elm.Kernel.Utils.lt
+
+
+gt : comparable -> comparable -> Bool
+gt =
+  Elm.Kernel.Utils.gt
+
+
+le : comparable -> comparable -> Bool
+le =
+  Elm.Kernel.Utils.le
+
+
+ge : comparable -> comparable -> Bool
+ge =
+  Elm.Kernel.Utils.ge
+
+
+min : comparable -> comparable -> comparable
+min x y =
+  if lt x y then x else y
+
+
+max : comparable -> comparable -> comparable
+max x y =
+  if gt x y then x else y
+
+
+compare : comparable -> comparable -> Order
+compare =
+  Elm.Kernel.Utils.compare
+
+
+type Order = LT | EQ | GT
+
+
+
+-- BOOLEANS
+
+
+type Bool = True | False
+
+
+not : Bool -> Bool
+not =
+  Elm.Kernel.Basics.not
+
+
+and : Bool -> Bool -> Bool
+and =
+  Elm.Kernel.Basics.and
+
+
+or : Bool -> Bool -> Bool
+or =
+  Elm.Kernel.Basics.or
+
+
+xor : Bool -> Bool -> Bool
+xor =
+  Elm.Kernel.Basics.xor
+
+
+-- APPEND
+
+
+append : appendable -> appendable -> appendable
+append =
+  Elm.Kernel.Utils.append
+
+
+
+-- FANCIER MATH
+
+
+modBy : Int -> Int -> Int
+modBy =
+  Elm.Kernel.Basics.modBy
+
+
+remainderBy : Int -> Int -> Int
+remainderBy =
+  Elm.Kernel.Basics.remainderBy
+
+
+negate : number -> number
+negate n =
+  -n
+
+
+abs : number -> number
+abs n =
+  if lt n 0 then -n else n
+
+
+clamp : number -> number -> number -> number
+clamp low high number =
+  if lt number low then
+    low
+  else if gt number high then
+    high
+  else
+    number
+
+
+sqrt : Float -> Float
+sqrt =
+  Elm.Kernel.Basics.sqrt
+
+
+logBase : Float -> Float -> Float
+logBase base number =
+  fdiv
+    (Elm.Kernel.Basics.log number)
+    (Elm.Kernel.Basics.log base)
+
+
+e : Float
+e =
+  Elm.Kernel.Basics.e
+
+
+-- ANGLES
+
+
+radians : Float -> Float
+radians angleInRadians =
+  angleInRadians
+
+
+degrees : Float -> Float
+degrees angleInDegrees =
+  fdiv (mul angleInDegrees pi) 180
+
+
+turns : Float -> Float
+turns angleInTurns =
+  mul (mul 2 pi) angleInTurns
+
+
+
+-- TRIGONOMETRY
+
+
+pi : Float
+pi =
+  Elm.Kernel.Basics.pi
+
+
+cos : Float -> Float
+cos =
+  Elm.Kernel.Basics.cos
+
+
+sin : Float -> Float
+sin =
+  Elm.Kernel.Basics.sin
+
+
+tan : Float -> Float
+tan =
+  Elm.Kernel.Basics.tan
+
+
+acos : Float -> Float
+acos =
+  Elm.Kernel.Basics.acos
+
+
+asin : Float -> Float
+asin =
+  Elm.Kernel.Basics.asin
+
+
+atan : Float -> Float
+atan =
+  Elm.Kernel.Basics.atan
+
+
+atan2 : Float -> Float -> Float
+atan2 =
+  Elm.Kernel.Basics.atan2
+
+
+
+-- POLAR COORDINATES
+
+
+fromPolar : (Float,Float) -> (Float,Float)
+fromPolar (radius, theta) =
+  ( mul radius (cos theta)
+  , mul radius (sin theta)
+  )
+
+
+toPolar : (Float,Float) -> (Float,Float)
+toPolar ( x, y ) =
+  ( sqrt (add (mul x x) (mul y y))
+  , atan2 y x
+  )
+
+
+
+-- CRAZY FLOATS
+
+
+isNaN : Float -> Bool
+isNaN =
+  Elm.Kernel.Basics.isNaN
+
+
+isInfinite : Float -> Bool
+isInfinite =
+  Elm.Kernel.Basics.isInfinite
+
+
+
+-- FUNCTION HELPERS
+
+
+composeL : (b -> c) -> (a -> b) -> (a -> c)
+composeL g f x =
+  g (f x)
+
+
+composeR : (a -> b) -> (b -> c) -> (a -> c)
+composeR f g x =
+  g (f x)
+
+
+apR : a -> (a -> b) -> b
+apR x f =
+  f x
+
+
+apL : (a -> b) -> a -> b
+apL f x =
+  f x
+
+
+identity : a -> a
+identity x =
+  x
+
+
+always : a -> b -> a
+always a _ =
+  a
+
+
+type Never = JustOneMore Never
+
+
+never : Never -> a
+never (JustOneMore nvr) =
+  never nvr
+
+
+--@ Char.elm
+module Char exposing (Char)
+
+import Basics exposing (Bool, Int, (&&), (||), (>=), (<=))
+import Elm.Kernel.Char
+
+type Char = Char
+
+
+--@ Maybe.elm
+module Maybe exposing (Maybe(..))
+
+type Maybe a
+    = Just a
+    | Nothing
+
+
+--@ Dict.elm
+module Dict exposing (Dict, member)
+
+
+type NColor
+    = Red
+    | Black
+
+
+type Dict k v
+    = RBNode_elm_builtin NColor k v (Dict k v) (Dict k v)
+    | RBEmpty_elm_builtin
+
+
+member : comparable -> Dict comparable v -> Bool
+member key dict =
+  case get key dict of
+    Just _ ->
+      True
+
+    Nothing ->
+      False
+
+
+--@ Set.elm
+module Set exposing (Set)
+
+
+import Dict
+
+
+type Set t =
+  Set_elm_builtin (Dict.Dict t ())
+
+
+member : comparable -> Set comparable -> Bool
+member key (Set_elm_builtin dict) =
+  Dict.member key dict
+`;
+
+export const stringSources = `
+--@ String.elm
+module String exposing (String, fromInt, fromFloat, slice, length, toFloat, uncons)
+
+
+import Elm.Kernel.List
+import Elm.Kernel.String
+
+
+type String = String
+
+
+fromInt : Int -> String
+fromInt =
+  \\_ -> ""
+
+
+fromFloat : Float -> String
+fromFloat =
+  \\_ -> ""
+
+
+slice : Int -> Int -> String -> String
+slice =
+  Elm.Kernel.String.slice
+
+
+length : String -> Int
+length =
+  Elm.Kernel.String.length
+
+
+toFloat : String -> Maybe Float
+toFloat =
+  Elm.Kernel.String.toFloat
+  
+
+uncons : String -> Maybe (Char, String)
+uncons =
+  Elm.Kernel.String.uncons
+`;
+
+export const parserSources = `
+--@ Parser.elm
+module Parser exposing
+  ( Parser, run
+  , int, float, number, symbol, keyword, variable, end
+  , succeed, (|=), (|.), lazy, andThen, problem
+  , oneOf, map, backtrackable, commit, token
+  , sequence, Trailing(..), loop, Step(..)
+  , spaces, lineComment, multiComment, Nestable(..)
+  , getChompedString, chompIf, chompWhile, chompUntil, chompUntilEndOr, mapChompedString
+  , DeadEnd, Problem(..), deadEndsToString
+  , withIndent, getIndent
+  , getPosition, getRow, getCol, getOffset, getSource
+  )
+
+
+import Char
+import Parser.Advanced as A exposing ((|=), (|.))
+import Set
+
+
+
+-- INFIX OPERATORS - see Parser.Advanced for why 5 and 6 were chosen
+
+
+infix left 5 (|=) = keeper
+infix left 6 (|.) = ignorer
+
+
+
+-- PARSERS
+
+type alias Parser a =
+  A.Parser Never Problem a
+
+
+
+-- RUN
+
+
+run : Parser a -> String -> Result (List DeadEnd) a
+run parser source =
+  case A.run parser source of
+    Ok a ->
+      Ok a
+
+    Err problems ->
+      Err (List.map problemToDeadEnd problems)
+
+
+problemToDeadEnd : A.DeadEnd Never Problem -> DeadEnd
+problemToDeadEnd p =
+  DeadEnd p.row p.col p.problem
+
+
+
+-- PROBLEMS
+
+
+type alias DeadEnd =
+  { row : Int
+  , col : Int
+  , problem : Problem
+  }
+
+
+type Problem
+  = Expecting String
+  | ExpectingInt
+  | ExpectingHex
+  | ExpectingOctal
+  | ExpectingBinary
+  | ExpectingFloat
+  | ExpectingNumber
+  | ExpectingVariable
+  | ExpectingSymbol String
+  | ExpectingKeyword String
+  | ExpectingEnd
+  | UnexpectedChar
+  | Problem String
+  | BadRepeat
+
+
+deadEndsToString : List DeadEnd -> String
+deadEndsToString deadEnds =
+  "TODO deadEndsToString"
+
+
+
+-- PIPELINES
+
+
+succeed : a -> Parser a
+succeed =
+  A.succeed
+
+
+keeper : Parser (a -> b) -> Parser a -> Parser b
+keeper =
+  (|=)
+
+
+ignorer : Parser keep -> Parser ignore -> Parser keep
+ignorer =
+  (|.)
+
+
+lazy : (() -> Parser a) -> Parser a
+lazy =
+  A.lazy
+
+
+andThen : (a -> Parser b) -> Parser a -> Parser b
+andThen =
+  A.andThen
+
+
+problem : String -> Parser a
+problem msg =
+  A.problem (Problem msg)
+
+
+
+-- BACKTRACKING
+
+oneOf : List (Parser a) -> Parser a
+oneOf =
+  A.oneOf
+
+
+map : (a -> b) -> Parser a -> Parser b
+map =
+  A.map
+
+
+backtrackable : Parser a -> Parser a
+backtrackable =
+  A.backtrackable
+
+
+commit : a -> Parser a
+commit =
+  A.commit
+
+
+
+-- TOKEN
+
+
+token : String -> Parser ()
+token str =
+  A.token (toToken str)
+
+
+toToken : String -> A.Token Problem
+toToken str =
+  A.Token str (Expecting str)
+
+
+
+-- LOOPS
+
+
+loop : state -> (state -> Parser (Step state a)) -> Parser a
+loop state callback =
+  A.loop state (\\s -> map toAdvancedStep (callback s))
+
+
+type Step state a
+  = Loop state
+  | Done a
+
+
+toAdvancedStep : Step s a -> A.Step s a
+toAdvancedStep step =
+  case step of
+    Loop s -> A.Loop s
+    Done a -> A.Done a
+
+
+
+-- NUMBERS
+
+
+int : Parser Int
+int =
+  A.int ExpectingInt ExpectingInt
+
+
+float : Parser Float
+float =
+  A.float ExpectingFloat ExpectingFloat
+
+
+
+-- NUMBER
+
+
+number
+  : { int : Maybe (Int -> a)
+    , hex : Maybe (Int -> a)
+    , octal : Maybe (Int -> a)
+    , binary : Maybe (Int -> a)
+    , float : Maybe (Float -> a)
+    }
+  -> Parser a
+number i =
+  A.number
+    { int = Result.fromMaybe ExpectingInt i.int
+    , hex = Result.fromMaybe ExpectingHex i.hex
+    , octal = Result.fromMaybe ExpectingOctal i.octal
+    , binary = Result.fromMaybe ExpectingBinary i.binary
+    , float = Result.fromMaybe ExpectingFloat i.float
+    , invalid = ExpectingNumber
+    , expecting = ExpectingNumber
+    }
+
+
+
+-- SYMBOL
+
+
+symbol : String -> Parser ()
+symbol str =
+  A.symbol (A.Token str (ExpectingSymbol str))
+
+
+
+-- KEYWORD
+
+
+keyword : String -> Parser ()
+keyword kwd =
+  A.keyword (A.Token kwd (ExpectingKeyword kwd))
+
+
+
+-- END
+
+
+end : Parser ()
+end =
+  A.end ExpectingEnd
+
+
+
+-- CHOMPED STRINGS
+
+
+getChompedString : Parser a -> Parser String
+getChompedString =
+  A.getChompedString
+
+
+mapChompedString : (String -> a -> b) -> Parser a -> Parser b
+mapChompedString =
+  A.mapChompedString
+
+
+
+chompIf : (Char -> Bool) -> Parser ()
+chompIf isGood =
+  A.chompIf isGood UnexpectedChar
+
+
+
+chompWhile : (Char -> Bool) -> Parser ()
+chompWhile =
+  A.chompWhile
+
+
+chompUntil : String -> Parser ()
+chompUntil str =
+  A.chompUntil (toToken str)
+
+
+chompUntilEndOr : String -> Parser ()
+chompUntilEndOr =
+  A.chompUntilEndOr
+
+
+
+-- INDENTATION
+
+
+withIndent : Int -> Parser a -> Parser a
+withIndent =
+  A.withIndent
+
+
+getIndent : Parser Int
+getIndent =
+  A.getIndent
+
+
+
+-- POSITION
+
+
+getPosition : Parser (Int, Int)
+getPosition =
+  A.getPosition
+
+
+getRow : Parser Int
+getRow =
+  A.getRow
+
+
+getCol : Parser Int
+getCol =
+  A.getCol
+
+
+getOffset : Parser Int
+getOffset =
+  A.getOffset
+
+
+getSource : Parser String
+getSource =
+  A.getSource
+
+
+
+-- VARIABLES
+
+
+variable :
+  { start : Char -> Bool
+  , inner : Char -> Bool
+  , reserved : Set.Set String
+  }
+  -> Parser String
+variable i =
+  A.variable
+    { start = i.start
+    , inner = i.inner
+    , reserved = i.reserved
+    , expecting = ExpectingVariable
+    }
+
+
+
+-- SEQUENCES
+
+
+sequence
+  : { start : String
+    , separator : String
+    , end : String
+    , spaces : Parser ()
+    , item : Parser a
+    , trailing : Trailing
+    }
+  -> Parser (List a)
+sequence i =
+  A.sequence
+    { start = toToken i.start
+    , separator = toToken i.separator
+    , end = toToken i.end
+    , spaces = i.spaces
+    , item = i.item
+    , trailing = toAdvancedTrailing i.trailing
+    }
+
+
+type Trailing = Forbidden | Optional | Mandatory
+
+
+toAdvancedTrailing : Trailing -> A.Trailing
+toAdvancedTrailing trailing =
+  case trailing of
+    Forbidden -> A.Forbidden
+    Optional -> A.Optional
+    Mandatory -> A.Mandatory
+
+
+
+-- WHITESPACE
+
+
+spaces : Parser ()
+spaces =
+  A.spaces
+
+
+lineComment : String -> Parser ()
+lineComment str =
+  A.lineComment (toToken str)
+
+
+multiComment : String -> String -> Nestable -> Parser ()
+multiComment open close nestable =
+  A.multiComment (toToken open) (toToken close) (toAdvancedNestable nestable)
+
+
+type Nestable = NotNestable | Nestable
+
+
+toAdvancedNestable : Nestable -> A.Nestable
+toAdvancedNestable nestable =
+  case nestable of
+    NotNestable -> A.NotNestable
+    Nestable -> A.Nestable
+
+
+--@ Parser/Advanced.elm
+module Parser.Advanced exposing
+  ( Parser, run, DeadEnd, inContext, Token(..)
+  , int, float, number, symbol, keyword, variable, end
+  , succeed, (|=), (|.), lazy, andThen, problem
+  , oneOf, map, backtrackable, commit, token
+  , sequence, Trailing(..), loop, Step(..)
+  , spaces, lineComment, multiComment, Nestable(..)
+  , getChompedString, chompIf, chompWhile, chompUntil, chompUntilEndOr, mapChompedString
+  , withIndent, getIndent
+  , getPosition, getRow, getCol, getOffset, getSource
+  )
+
+
+import Char
+import Elm.Kernel.Parser
+import Set
+
+
+
+-- INFIX OPERATORS
+
+
+infix left 5 (|=) = keeper
+infix left 6 (|.) = ignorer
+
+
+
+
+
+-- PARSERS
+
+
+type Parser context problem value =
+  Parser (State context -> PStep context problem value)
+
+
+type PStep context problem value
+  = Good Bool value (State context)
+  | Bad Bool (Bag context problem)
+
+
+type alias State context =
+  { src : String
+  , offset : Int
+  , indent : Int
+  , context : List (Located context)
+  , row : Int
+  , col : Int
+  }
+
+
+type alias Located context =
+  { row : Int
+  , col : Int
+  , context : context
+  }
+
+
+
+-- RUN
+
+
+run : Parser c x a -> String -> Result (List (DeadEnd c x)) a
+run (Parser parse) src =
+  case parse { src = src, offset = 0, indent = 1, context = [], row = 1, col = 1} of
+    Good _ value _ ->
+      Ok value
+
+    Bad _ bag ->
+      Err (bagToList bag [])
+
+
+
+-- PROBLEMS
+
+
+type alias DeadEnd context problem =
+  { row : Int
+  , col : Int
+  , problem : problem
+  , contextStack : List { row : Int, col : Int, context : context }
+  }
+
+
+type Bag c x
+  = Empty
+  | AddRight (Bag c x) (DeadEnd c x)
+  | Append (Bag c x) (Bag c x)
+
+
+fromState : State c -> x -> Bag c x
+fromState s x =
+  AddRight Empty (DeadEnd s.row s.col x s.context)
+
+
+fromInfo : Int -> Int -> x -> List (Located c) -> Bag c x
+fromInfo row col x context =
+  AddRight Empty (DeadEnd row col x context)
+
+
+bagToList : Bag c x -> List (DeadEnd c x) -> List (DeadEnd c x)
+bagToList bag list =
+  case bag of
+    Empty ->
+      list
+
+    AddRight bag1 x ->
+      bagToList bag1 (x :: list)
+
+    Append bag1 bag2 ->
+      bagToList bag1 (bagToList bag2 list)
+
+
+
+-- PRIMITIVES
+
+succeed : a -> Parser c x a
+succeed a =
+  Parser <| \\s ->
+    Good False a s
+
+
+problem : x -> Parser c x a
+problem x =
+  Parser <| \\s ->
+    Bad False (fromState s x)
+
+
+
+-- MAPPING
+
+
+map : (a -> b) -> Parser c x a -> Parser c x b
+map func (Parser parse) =
+  Parser <| \\s0 ->
+    case parse s0 of
+      Good p a s1 ->
+        Good p (func a) s1
+
+      Bad p x ->
+        Bad p x
+
+
+map2 : (a -> b -> value) -> Parser c x a -> Parser c x b -> Parser c x value
+map2 func (Parser parseA) (Parser parseB) =
+  Parser <| \\s0 ->
+    case parseA s0 of
+      Bad p x ->
+        Bad p x
+
+      Good p1 a s1 ->
+        case parseB s1 of
+          Bad p2 x ->
+            Bad (p1 || p2) x
+
+          Good p2 b s2 ->
+            Good (p1 || p2) (func a b) s2
+
+
+keeper : Parser c x (a -> b) -> Parser c x a -> Parser c x b
+keeper parseFunc parseArg =
+  map2 (<|) parseFunc parseArg
+
+
+ignorer : Parser c x keep -> Parser c x ignore -> Parser c x keep
+ignorer keepParser ignoreParser =
+  map2 always keepParser ignoreParser
+
+
+
+-- AND THEN
+
+
+andThen : (a -> Parser c x b) -> Parser c x a -> Parser c x b
+andThen callback (Parser parseA) =
+  Parser <| \\s0 ->
+    case parseA s0 of
+      Bad p x ->
+        Bad p x
+
+      Good p1 a s1 ->
+        let
+          (Parser parseB) =
+            callback a
+        in
+        case parseB s1 of
+          Bad p2 x ->
+            Bad (p1 || p2) x
+
+          Good p2 b s2 ->
+            Good (p1 || p2) b s2
+
+
+
+-- LAZY
+
+
+lazy : (() -> Parser c x a) -> Parser c x a
+lazy thunk =
+  Parser <| \\s ->
+    let
+      (Parser parse) =
+        thunk ()
+    in
+    parse s
+
+
+
+-- ONE OF
+
+
+oneOf : List (Parser c x a) -> Parser c x a
+oneOf parsers =
+  Parser <| \\s -> oneOfHelp s Empty parsers
+
+
+oneOfHelp : State c -> Bag c x -> List (Parser c x a) -> PStep c x a
+oneOfHelp s0 bag parsers =
+  case parsers of
+    [] ->
+      Bad False bag
+
+    Parser parse :: remainingParsers ->
+      case parse s0 of
+        Good _ _ _ as step ->
+          step
+
+        Bad p x as step ->
+          if p then
+            step
+          else
+            oneOfHelp s0 (Append bag x) remainingParsers
+
+
+
+-- LOOP
+
+
+type Step state a
+  = Loop state
+  | Done a
+
+
+loop : state -> (state -> Parser c x (Step state a)) -> Parser c x a
+loop state callback =
+  Parser <| \\s ->
+    loopHelp False state callback s
+
+
+loopHelp : Bool -> state -> (state -> Parser c x (Step state a)) -> State c -> PStep c x a
+loopHelp p state callback s0 =
+  let
+    (Parser parse) =
+      callback state
+  in
+  case parse s0 of
+    Good p1 step s1 ->
+      case step of
+        Loop newState ->
+          loopHelp (p || p1) newState callback s1
+
+        Done result ->
+          Good (p || p1) result s1
+
+    Bad p1 x ->
+      Bad (p || p1) x
+
+
+
+-- BACKTRACKABLE
+
+
+backtrackable : Parser c x a -> Parser c x a
+backtrackable (Parser parse) =
+  Parser <| \\s0 ->
+    case parse s0 of
+      Bad _ x ->
+        Bad False x
+
+      Good _ a s1 ->
+        Good False a s1
+
+
+commit : a -> Parser c x a
+commit a =
+  Parser <| \\s -> Good True a s
+
+
+
+-- SYMBOL
+
+
+symbol : Token x -> Parser c x ()
+symbol =
+  token
+
+
+
+-- KEYWORD
+
+
+keyword : Token x -> Parser c x ()
+keyword (Token kwd expecting) =
+  let
+    progress =
+      not (String.isEmpty kwd)
+  in
+  Parser <| \\s ->
+    let
+      (newOffset, newRow, newCol) =
+        isSubString kwd s.offset s.row s.col s.src
+    in
+    if newOffset == -1 || 0 <= isSubChar (\\c -> Char.isAlphaNum c || c == '_') newOffset s.src then
+      Bad False (fromState s expecting)
+    else
+      Good progress ()
+        { src = s.src
+        , offset = newOffset
+        , indent = s.indent
+        , context = s.context
+        , row = newRow
+        , col = newCol
+        }
+
+
+
+-- TOKEN
+
+
+type Token x = Token String x
+
+
+token : Token x -> Parser c x ()
+token (Token str expecting) =
+  let
+    progress =
+      not (String.isEmpty str)
+  in
+  Parser <| \\s ->
+    let
+      (newOffset, newRow, newCol) =
+        isSubString str s.offset s.row s.col s.src
+    in
+    if newOffset == -1 then
+      Bad False (fromState s expecting)
+    else
+      Good progress ()
+        { src = s.src
+        , offset = newOffset
+        , indent = s.indent
+        , context = s.context
+        , row = newRow
+        , col = newCol
+        }
+
+
+
+-- INT
+
+
+int : x -> x -> Parser c x Int
+int expecting invalid =
+  number
+    { int = Ok identity
+    , hex = Err invalid
+    , octal = Err invalid
+    , binary = Err invalid
+    , float = Err invalid
+    , invalid = invalid
+    , expecting = expecting
+    }
+
+
+
+-- FLOAT
+
+
+float : x -> x -> Parser c x Float
+float expecting invalid =
+  number
+    { int = Ok toFloat
+    , hex = Err invalid
+    , octal = Err invalid
+    , binary = Err invalid
+    , float = Ok identity
+    , invalid = invalid
+    , expecting = expecting
+    }
+
+
+
+-- NUMBER
+
+
+number
+  : { int : Result x (Int -> a)
+    , hex : Result x (Int -> a)
+    , octal : Result x (Int -> a)
+    , binary : Result x (Int -> a)
+    , float : Result x (Float -> a)
+    , invalid : x
+    , expecting : x
+    }
+  -> Parser c x a
+number c =
+  Parser <| \\s ->
+    if isAsciiCode 0x30 {- 0 -} s.offset s.src then
+      let
+        zeroOffset = s.offset + 1
+        baseOffset = zeroOffset + 1
+      in
+      if isAsciiCode 0x78 {- x -} zeroOffset s.src then
+        finalizeInt c.invalid c.hex baseOffset (consumeBase16 baseOffset s.src) s
+      else if isAsciiCode 0x6F {- o -} zeroOffset s.src then
+        finalizeInt c.invalid c.octal baseOffset (consumeBase 8 baseOffset s.src) s
+      else if isAsciiCode 0x62 {- b -} zeroOffset s.src then
+        finalizeInt c.invalid c.binary baseOffset (consumeBase 2 baseOffset s.src) s
+      else
+        finalizeFloat c.invalid c.expecting c.int c.float (zeroOffset, 0) s
+
+    else
+      finalizeFloat c.invalid c.expecting c.int c.float (consumeBase 10 s.offset s.src) s
+
+
+consumeBase : Int -> Int -> String -> (Int, Int)
+consumeBase =
+  Elm.Kernel.Parser.consumeBase
+
+
+consumeBase16 : Int -> String -> (Int, Int)
+consumeBase16 =
+  Elm.Kernel.Parser.consumeBase16
+
+
+finalizeInt : x -> Result x (Int -> a) -> Int -> (Int, Int) -> State c -> PStep c x a
+finalizeInt invalid handler startOffset (endOffset, n) s =
+  case handler of
+    Err x ->
+      Bad True (fromState s x)
+
+    Ok toValue ->
+      if startOffset == endOffset
+        then Bad (s.offset < startOffset) (fromState s invalid)
+        else Good True (toValue n) (bumpOffset endOffset s)
+
+
+bumpOffset : Int -> State c -> State c
+bumpOffset newOffset s =
+  { src = s.src
+  , offset = newOffset
+  , indent = s.indent
+  , context = s.context
+  , row = s.row
+  , col = s.col + (newOffset - s.offset)
+  }
+
+
+finalizeFloat : x -> x -> Result x (Int -> a) -> Result x (Float -> a) -> (Int, Int) -> State c -> PStep c x a
+finalizeFloat invalid expecting intSettings floatSettings intPair s =
+  let
+    intOffset = Tuple.first intPair
+    floatOffset = consumeDotAndExp intOffset s.src
+  in
+  if floatOffset < 0 then
+    Bad True (fromInfo s.row (s.col - (floatOffset + s.offset)) invalid s.context)
+
+  else if s.offset == floatOffset then
+    Bad False (fromState s expecting)
+
+  else if intOffset == floatOffset then
+    finalizeInt invalid intSettings s.offset intPair s
+
+  else
+    case floatSettings of
+      Err x ->
+        Bad True (fromState s invalid)
+
+      Ok toValue ->
+        case String.toFloat (String.slice s.offset floatOffset s.src) of
+          Nothing -> Bad True (fromState s invalid)
+          Just n -> Good True (toValue n) (bumpOffset floatOffset s)
+
+
+--
+-- On a failure, returns negative index of problem.
+--
+consumeDotAndExp : Int -> String -> Int
+consumeDotAndExp offset src =
+  if isAsciiCode 0x2E {- . -} offset src then
+    consumeExp (chompBase10 (offset + 1) src) src
+  else
+    consumeExp offset src
+
+
+--
+-- On a failure, returns negative index of problem.
+--
+consumeExp : Int -> String -> Int
+consumeExp offset src =
+  if isAsciiCode 0x65 {- e -} offset src || isAsciiCode 0x45 {- E -} offset src then
+    let
+      eOffset = offset + 1
+
+      expOffset =
+        if isAsciiCode 0x2B {- + -} eOffset src || isAsciiCode 0x2D {- - -} eOffset src then
+          eOffset + 1
+        else
+          eOffset
+
+      newOffset = chompBase10 expOffset src
+    in
+    if expOffset == newOffset then
+      -newOffset
+    else
+      newOffset
+
+  else
+    offset
+
+
+chompBase10 : Int -> String -> Int
+chompBase10 =
+  Elm.Kernel.Parser.chompBase10
+
+
+
+-- END
+
+
+end : x -> Parser c x ()
+end x =
+  Parser <| \\s ->
+    if String.length s.src == s.offset then
+      Good False () s
+    else
+      Bad False (fromState s x)
+
+
+
+-- CHOMPED STRINGS
+
+
+getChompedString : Parser c x a -> Parser c x String
+getChompedString parser =
+  mapChompedString always parser
+
+
+mapChompedString : (String -> a -> b) -> Parser c x a -> Parser c x b
+mapChompedString func (Parser parse) =
+  Parser <| \\s0 ->
+    case parse s0 of
+      Bad p x ->
+        Bad p x
+
+      Good p a s1 ->
+        Good p (func (String.slice s0.offset s1.offset s0.src) a) s1
+
+
+
+-- CHOMP IF
+
+
+chompIf : (Char -> Bool) -> x -> Parser c x ()
+chompIf isGood expecting =
+  Parser <| \\s ->
+    let
+      newOffset = isSubChar isGood s.offset s.src
+    in
+    -- not found
+    if newOffset == -1 then
+      Bad False (fromState s expecting)
+
+    -- newline
+    else if newOffset == -2 then
+      Good True ()
+        { src = s.src
+        , offset = s.offset + 1
+        , indent = s.indent
+        , context = s.context
+        , row = s.row + 1
+        , col = 1
+        }
+
+    -- found
+    else
+      Good True ()
+        { src = s.src
+        , offset = newOffset
+        , indent = s.indent
+        , context = s.context
+        , row = s.row
+        , col = s.col + 1
+        }
+
+
+
+-- CHOMP WHILE
+
+
+chompWhile : (Char -> Bool) -> Parser c x ()
+chompWhile isGood =
+  Parser <| \\s ->
+    chompWhileHelp isGood s.offset s.row s.col s
+
+
+chompWhileHelp : (Char -> Bool) -> Int -> Int -> Int -> State c -> PStep c x ()
+chompWhileHelp isGood offset row col s0 =
+  let
+    newOffset = isSubChar isGood offset s0.src
+  in
+  -- no match
+  if newOffset == -1 then
+    Good (s0.offset < offset) ()
+      { src = s0.src
+      , offset = offset
+      , indent = s0.indent
+      , context = s0.context
+      , row = row
+      , col = col
+      }
+
+  -- matched a newline
+  else if newOffset == -2 then
+    chompWhileHelp isGood (offset + 1) (row + 1) 1 s0
+
+  -- normal match
+  else
+    chompWhileHelp isGood newOffset row (col + 1) s0
+
+
+
+-- CHOMP UNTIL
+
+
+chompUntil : Token x -> Parser c x ()
+chompUntil (Token str expecting) =
+  Parser <| \\s ->
+    let
+      (newOffset, newRow, newCol) =
+        findSubString str s.offset s.row s.col s.src
+    in
+    if newOffset == -1 then
+      Bad False (fromInfo newRow newCol expecting s.context)
+
+    else
+      Good (s.offset < newOffset) ()
+        { src = s.src
+        , offset = newOffset
+        , indent = s.indent
+        , context = s.context
+        , row = newRow
+        , col = newCol
+        }
+
+
+chompUntilEndOr : String -> Parser c x ()
+chompUntilEndOr str =
+  Parser <| \\s ->
+    let
+      (newOffset, newRow, newCol) =
+        Elm.Kernel.Parser.findSubString str s.offset s.row s.col s.src
+
+      adjustedOffset =
+        if newOffset < 0 then String.length s.src else newOffset
+    in
+    Good (s.offset < adjustedOffset) ()
+      { src = s.src
+      , offset = adjustedOffset
+      , indent = s.indent
+      , context = s.context
+      , row = newRow
+      , col = newCol
+      }
+
+
+
+-- CONTEXT
+
+
+inContext : context -> Parser context x a -> Parser context x a
+inContext context (Parser parse) =
+  Parser <| \\s0 ->
+    case parse (changeContext (Located s0.row s0.col context :: s0.context) s0) of
+      Good p a s1 ->
+        Good p a (changeContext s0.context s1)
+
+      Bad _ _ as step ->
+        step
+
+
+changeContext : List (Located c) -> State c -> State c
+changeContext newContext s =
+  { src = s.src
+  , offset = s.offset
+  , indent = s.indent
+  , context = newContext
+  , row = s.row
+  , col = s.col
+  }
+
+
+
+-- INDENTATION
+
+
+getIndent : Parser c x Int
+getIndent =
+  Parser <| \\s -> Good False s.indent s
+
+
+withIndent : Int -> Parser c x a -> Parser c x a
+withIndent newIndent (Parser parse) =
+  Parser <| \\s0 ->
+    case parse (changeIndent newIndent s0) of
+      Good p a s1 ->
+        Good p a (changeIndent s0.indent s1)
+
+      Bad p x ->
+        Bad p x
+
+
+changeIndent : Int -> State c -> State c
+changeIndent newIndent s =
+  { src = s.src
+  , offset = s.offset
+  , indent = newIndent
+  , context = s.context
+  , row = s.row
+  , col = s.col
+  }
+
+
+
+-- POSITION
+
+
+getPosition : Parser c x (Int, Int)
+getPosition =
+  Parser <| \\s -> Good False (s.row, s.col) s
+
+
+getRow : Parser c x Int
+getRow =
+  Parser <| \\s -> Good False s.row s
+
+
+getCol : Parser c x Int
+getCol =
+  Parser <| \\s -> Good False s.col s
+
+
+getOffset : Parser c x Int
+getOffset =
+  Parser <| \\s -> Good False s.offset s
+
+
+getSource : Parser c x String
+getSource =
+  Parser <| \\s -> Good False s.src s
+
+
+
+-- LOW-LEVEL HELPERS
+
+
+isSubString : String -> Int -> Int -> Int -> String -> (Int, Int, Int)
+isSubString =
+  Elm.Kernel.Parser.isSubString
+
+
+isSubChar : (Char -> Bool) -> Int -> String -> Int
+isSubChar =
+  Elm.Kernel.Parser.isSubChar
+
+
+isAsciiCode : Int -> Int -> String -> Bool
+isAsciiCode =
+  Elm.Kernel.Parser.isAsciiCode
+
+
+findSubString : String -> Int -> Int -> Int -> String -> (Int, Int, Int)
+findSubString =
+  Elm.Kernel.Parser.findSubString
+
+
+
+-- VARIABLES
+
+
+variable :
+  { start : Char -> Bool
+  , inner : Char -> Bool
+  , reserved : Set.Set String
+  , expecting : x
+  }
+  -> Parser c x String
+variable i =
+  Parser <| \\s ->
+    let
+      firstOffset =
+        isSubChar i.start s.offset s.src
+    in
+    if firstOffset == -1 then
+      Bad False (fromState s i.expecting)
+    else
+      let
+        s1 =
+          if firstOffset == -2 then
+            varHelp i.inner (s.offset + 1) (s.row + 1) 1 s.src s.indent s.context
+          else
+            varHelp i.inner firstOffset s.row (s.col + 1) s.src s.indent s.context
+
+        name =
+          String.slice s.offset s1.offset s.src
+      in
+      if Set.member name i.reserved then
+        Bad False (fromState s i.expecting)
+      else
+        Good True name s1
+
+
+varHelp : (Char -> Bool) -> Int -> Int -> Int -> String -> Int -> List (Located c) -> State c
+varHelp isGood offset row col src indent context =
+  let
+    newOffset = isSubChar isGood offset src
+  in
+  if newOffset == -1 then
+    { src = src
+    , offset = offset
+    , indent = indent
+    , context = context
+    , row = row
+    , col = col
+    }
+
+  else if newOffset == -2 then
+    varHelp isGood (offset + 1) (row + 1) 1 src indent context
+
+  else
+    varHelp isGood newOffset row (col + 1) src indent context
+
+
+
+-- SEQUENCES
+
+
+sequence
+  : { start : Token x
+    , separator : Token x
+    , end : Token x
+    , spaces : Parser c x ()
+    , item : Parser c x a
+    , trailing : Trailing
+    }
+  -> Parser c x (List a)
+sequence i =
+  skip (token i.start) <|
+  skip i.spaces <|
+    sequenceEnd (token i.end) i.spaces i.item (token i.separator) i.trailing
+
+
+type Trailing = Forbidden | Optional | Mandatory
+
+
+skip : Parser c x ignore -> Parser c x keep -> Parser c x keep
+skip iParser kParser =
+  map2 revAlways iParser kParser
+
+
+revAlways : a -> b -> b
+revAlways _ b =
+  b
+
+
+sequenceEnd : Parser c x () -> Parser c x () -> Parser c x a -> Parser c x () -> Trailing -> Parser c x (List a)
+sequenceEnd ender ws parseItem sep trailing =
+  let
+    chompRest item =
+      case trailing of
+        Forbidden ->
+          loop [item] (sequenceEndForbidden ender ws parseItem sep)
+
+        Optional ->
+          loop [item] (sequenceEndOptional ender ws parseItem sep)
+
+        Mandatory ->
+          ignorer
+            ( skip ws <| skip sep <| skip ws <|
+                loop [item] (sequenceEndMandatory ws parseItem sep)
+            )
+            ender
+  in
+  oneOf
+    [ parseItem |> andThen chompRest
+    , ender |> map (\\_ -> [])
+    ]
+
+
+sequenceEndForbidden : Parser c x () -> Parser c x () -> Parser c x a -> Parser c x () -> List a -> Parser c x (Step (List a) (List a))
+sequenceEndForbidden ender ws parseItem sep revItems =
+  let
+    chompRest item =
+      sequenceEndForbidden ender ws parseItem sep (item :: revItems)
+  in
+  skip ws <|
+    oneOf
+      [ skip sep <| skip ws <| map (\\item -> Loop (item :: revItems)) parseItem
+      , ender |> map (\\_ -> Done (List.reverse revItems))
+      ]
+
+
+sequenceEndOptional : Parser c x () -> Parser c x () -> Parser c x a -> Parser c x () -> List a -> Parser c x (Step (List a) (List a))
+sequenceEndOptional ender ws parseItem sep revItems =
+  let
+    parseEnd =
+      map (\\_ -> Done (List.reverse revItems)) ender
+  in
+  skip ws <|
+    oneOf
+      [ skip sep <| skip ws <|
+          oneOf
+            [ parseItem |> map (\\item -> Loop (item :: revItems))
+            , parseEnd
+            ]
+      , parseEnd
+      ]
+
+
+sequenceEndMandatory : Parser c x () -> Parser c x a -> Parser c x () -> List a -> Parser c x (Step (List a) (List a))
+sequenceEndMandatory ws parseItem sep revItems =
+  oneOf
+    [ map (\\item -> Loop (item :: revItems)) <|
+        ignorer parseItem (ignorer ws (ignorer sep ws))
+    , map (\\_ -> Done (List.reverse revItems)) (succeed ())
+    ]
+
+
+
+-- WHITESPACE
+
+
+spaces : Parser c x ()
+spaces =
+  chompWhile (\\c -> c == ' ' || c == '\\n' || c == '\\r')
+
+
+lineComment : Token x -> Parser c x ()
+lineComment start =
+  ignorer (token start) (chompUntilEndOr "\\n")
+
+
+multiComment : Token x -> Token x -> Nestable -> Parser c x ()
+multiComment open close nestable =
+  case nestable of
+    NotNestable ->
+      ignorer (token open) (chompUntil close)
+
+    Nestable ->
+      nestableComment open close
+
+
+type Nestable = NotNestable | Nestable
+
+
+nestableComment : Token x -> Token x -> Parser c x ()
+nestableComment (Token oStr oX as open) (Token cStr cX as close) =
+  case String.uncons oStr of
+    Nothing ->
+      problem oX
+
+    Just (openChar, _) ->
+      case String.uncons cStr of
+        Nothing ->
+          problem cX
+
+        Just (closeChar, _) ->
+          let
+            isNotRelevant char =
+              char /= openChar && char /= closeChar
+
+            chompOpen =
+              token open
+          in
+          ignorer chompOpen (nestableHelp isNotRelevant chompOpen (token close) cX 1)
+
+
+nestableHelp : (Char -> Bool) -> Parser c x () -> Parser c x () -> x -> Int -> Parser c x ()
+nestableHelp isNotRelevant open close expectingClose nestLevel =
+  skip (chompWhile isNotRelevant) <|
+    oneOf
+      [ if nestLevel == 1 then
+          close
+        else
+          close
+            |> andThen (\\_ -> nestableHelp isNotRelevant open close expectingClose (nestLevel - 1))
+      , open
+          |> andThen (\\_ -> nestableHelp isNotRelevant open close expectingClose (nestLevel + 1))
+      , chompIf isChar expectingClose
+          |> andThen (\\_ -> nestableHelp isNotRelevant open close expectingClose nestLevel)
+      ]
+
+
+isChar : Char -> Bool
+isChar char =
+  True
+`;
+
+export const listSources = `
+--@ List.elm
+module List exposing ((::), reverse, foldl)
+
+import Basics exposing (..)
+import Elm.Kernel.List
+
+infix right 5 (::) = cons
+
+cons : a -> List a -> List a
+cons =
+  Elm.Kernel.List.cons
+
+
+reverse : List a -> List a
+reverse list =
+  foldl cons [] list
+
+
+foldl : (a -> b -> b) -> b -> List a -> b
+foldl func acc list =
+  case list of
+    [] ->
+      acc
+
+    x :: xs ->
+      foldl func (func x acc) xs
+`;
diff --git a/test/findTestsProvider.test.ts b/test/findTestsProvider.test.ts
index 8c00152..aababf0 100644
--- a/test/findTestsProvider.test.ts
+++ b/test/findTestsProvider.test.ts
@@ -9,7 +9,7 @@ import { TestSuite } from "../src/protocol";
 
 const basicsSources = `
 --@ Basics.elm
-module Basics exposing ((<|),(++), Int, Float, Bool(..), Order(..), negate)
+module Basics exposing ((<|), (++), Int, Float, Bool(..), Order(..), negate)
 
 infix left  0 (<|) = apL
 infix right 5 (++) = append