@effect/language-service 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +216 -114
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -167,7 +167,7 @@ var let_ = (map8) => dual(3, (self, name, f) => map8(self, (a) => Object.assign(
167
167
  var bindTo = (map8) => dual(2, (self, name) => map8(self, (a) => ({
168
168
  [name]: a
169
169
  })));
170
- var bind = (map8, flatMap5) => dual(3, (self, name, f) => flatMap5(self, (a) => map8(f(a), (b) => Object.assign({}, a, {
170
+ var bind = (map8, flatMap6) => dual(3, (self, name, f) => flatMap6(self, (a) => map8(f(a), (b) => Object.assign({}, a, {
171
171
  [name]: b
172
172
  }))));
173
173
 
@@ -930,6 +930,8 @@ var getOrUndefined2 = /* @__PURE__ */ getOrElse2(constUndefined);
930
930
  var fromIterable = (collection) => Array.isArray(collection) ? collection : Array.from(collection);
931
931
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
932
932
  var isArray = Array.isArray;
933
+ var isEmptyArray = (self) => self.length === 0;
934
+ var isEmptyReadonlyArray = isEmptyArray;
933
935
  var isNonEmptyReadonlyArray = isNonEmptyArray;
934
936
  var isOutOfBound = (i, as) => i < 0 || i >= as.length;
935
937
  var get = /* @__PURE__ */ dual(2, (self, index) => {
@@ -954,18 +956,20 @@ var sort = /* @__PURE__ */ dual(2, (self, O) => {
954
956
  });
955
957
  var empty = () => [];
956
958
  var map2 = /* @__PURE__ */ dual(2, (self, f) => self.map(f));
957
- var filterMap = /* @__PURE__ */ dual(2, (self, f) => {
958
- const as = fromIterable(self);
959
+ var flatMap2 = /* @__PURE__ */ dual(2, (self, f) => {
960
+ if (isEmptyReadonlyArray(self)) {
961
+ return [];
962
+ }
959
963
  const out = [];
960
- for (let i = 0; i < as.length; i++) {
961
- const o = f(as[i], i);
962
- if (isSome2(o)) {
963
- out.push(o.value);
964
+ for (let i = 0; i < self.length; i++) {
965
+ const inner = f(self[i], i);
966
+ for (let j = 0; j < inner.length; j++) {
967
+ out.push(inner[j]);
964
968
  }
965
969
  }
966
970
  return out;
967
971
  });
968
- var getSomes = /* @__PURE__ */ filterMap(identity);
972
+ var flatten = /* @__PURE__ */ flatMap2(identity);
969
973
  var filter = /* @__PURE__ */ dual(2, (self, predicate) => {
970
974
  const as = fromIterable(self);
971
975
  const out = [];
@@ -2719,7 +2723,7 @@ var run = (fa) => {
2719
2723
  var succeed = (value) => new Nano(() => ({ _tag: "Right", right: value }));
2720
2724
  var fail3 = (value) => new Nano(() => ({ _tag: "Left", left: value }));
2721
2725
  var sync = (value) => new Nano(() => ({ _tag: "Right", right: value() }));
2722
- var flatMap4 = dual(2, (fa, f) => new Nano((ctx) => {
2726
+ var flatMap5 = dual(2, (fa, f) => new Nano((ctx) => {
2723
2727
  const result = fa.run(ctx);
2724
2728
  if (result._tag !== "Right") return result;
2725
2729
  return f(result.right).run(ctx);
@@ -2782,102 +2786,11 @@ var option = (fa) => new Nano((ctx) => {
2782
2786
  }
2783
2787
  });
2784
2788
 
2785
- // src/core/LSP.ts
2786
- var RefactorNotApplicableError = class extends TaggedError("RefactorNotApplicableError") {
2787
- };
2788
- function createRefactor(definition) {
2789
- return definition;
2790
- }
2791
- function createDiagnostic(definition) {
2792
- return definition;
2793
- }
2794
- function createCompletion(definition) {
2795
- return definition;
2796
- }
2797
- var PluginOptions = Tag("PluginOptions");
2798
- var SourceFileNotFoundError = class extends TaggedError("SourceFileNotFoundError") {
2799
- };
2800
- var getSemanticDiagnostics = fn("LSP.getSemanticDiagnostics")(function* (diagnostics2, sourceFile) {
2801
- const effectDiagnostics = [];
2802
- for (const diagnostic of diagnostics2) {
2803
- const result = yield* option(diagnostic.apply(sourceFile));
2804
- if (isSome2(result)) {
2805
- effectDiagnostics.push(...result.value.map((_) => ({
2806
- file: sourceFile,
2807
- start: _.node.getStart(sourceFile),
2808
- length: _.node.getEnd() - _.node.getStart(sourceFile),
2809
- messageText: _.messageText,
2810
- category: _.category,
2811
- code: diagnostic.code,
2812
- source: "effect"
2813
- })));
2814
- }
2815
- }
2816
- return effectDiagnostics;
2817
- });
2818
- var getCodeFixesAtPosition = fn("LSP.getCodeFixesAtPosition")(function* (diagnostics2, sourceFile, start, end, errorCodes) {
2819
- const runnableDiagnostics = diagnostics2.filter((_) => errorCodes.indexOf(_.code) > -1);
2820
- const applicableFixes = [];
2821
- for (const diagnostic of runnableDiagnostics) {
2822
- const result = yield* option(diagnostic.apply(sourceFile));
2823
- if (isSome2(result)) {
2824
- applicableFixes.push(
2825
- ...pipe(
2826
- result.value,
2827
- filter(
2828
- (_) => _.node.getStart(sourceFile) === start && _.node.getEnd() === end
2829
- ),
2830
- map2((_) => _.fix),
2831
- getSomes
2832
- )
2833
- );
2834
- }
2835
- }
2836
- return applicableFixes;
2837
- });
2838
- var getApplicableRefactors = fn("LSP.getApplicableRefactors")(function* (refactors2, sourceFile, positionOrRange) {
2839
- const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
2840
- const effectRefactors = [];
2841
- for (const refactor of refactors2) {
2842
- const result = yield* option(refactor.apply(sourceFile, textRange));
2843
- if (isSome2(result)) {
2844
- effectRefactors.push({
2845
- name: refactor.name,
2846
- description: refactor.description,
2847
- actions: [{
2848
- name: refactor.name,
2849
- description: result.value.description,
2850
- kind: result.value.kind
2851
- }]
2852
- });
2853
- }
2854
- }
2855
- return effectRefactors;
2856
- });
2857
- var getEditsForRefactor = fn("LSP.getEditsForRefactor")(function* (refactors2, sourceFile, positionOrRange, refactorName) {
2858
- const refactor = refactors2.find((refactor2) => refactor2.name === refactorName);
2859
- if (!refactor) {
2860
- return yield* fail3(new RefactorNotApplicableError());
2861
- }
2862
- const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
2863
- return yield* refactor.apply(sourceFile, textRange);
2864
- });
2865
- var getCompletionsAtPosition = fn("LSP.getCompletionsAtPosition")(function* (completions2, sourceFile, position, options, formatCodeSettings) {
2866
- const effectCompletions = [];
2867
- for (const completion of completions2) {
2868
- const result = yield* completion.apply(sourceFile, position, options, formatCodeSettings);
2869
- effectCompletions.push(
2870
- ...result.map((_) => ({ sortText: "11", ..._ }))
2871
- );
2872
- }
2873
- return effectCompletions;
2874
- });
2875
-
2876
- // src/utils/TypeScriptApi.ts
2789
+ // src/core/TypeScriptApi.ts
2877
2790
  var TypeScriptApi = Tag("TypeScriptApi");
2878
2791
  var ChangeTracker = Tag("ChangeTracker");
2879
2792
 
2880
- // src/utils/AST.ts
2793
+ // src/core/AST.ts
2881
2794
  function collectSelfAndAncestorNodesInRange(node, textRange) {
2882
2795
  return sync(() => {
2883
2796
  let result = empty();
@@ -2910,6 +2823,21 @@ var findNodeAtPosition = fn("AST.findNodeAtPosition")(function* (sourceFile, pos
2910
2823
  if (!result) return yield* fail3(new NodeNotFoundError());
2911
2824
  return result;
2912
2825
  });
2826
+ var getCommentAtPosition = fn("TypeScriptApi.getCommentAtPosition")(function* (sourceFile, pos) {
2827
+ const ts = yield* service(TypeScriptApi);
2828
+ const token = yield* findNodeAtPosition(sourceFile, pos);
2829
+ if (token === void 0 || token.kind === ts.SyntaxKind.JsxText || pos >= token.end - (ts.tokenToString(token.kind) || "").length) {
2830
+ return yield* fail3(new NodeNotFoundError());
2831
+ }
2832
+ const startPos = token.pos === 0 ? (ts.getShebang(sourceFile.text) || "").length : token.pos;
2833
+ if (startPos === 0) return yield* fail3(new NodeNotFoundError());
2834
+ const result = ts.forEachTrailingCommentRange(sourceFile.text, startPos, isCommentInRange, pos) || ts.forEachLeadingCommentRange(sourceFile.text, startPos, isCommentInRange, pos);
2835
+ if (!result) return yield* fail3(new NodeNotFoundError());
2836
+ return result;
2837
+ });
2838
+ function isCommentInRange(pos, end, kind, _nl, at) {
2839
+ return at >= pos && at < end ? { pos, end, kind } : void 0;
2840
+ }
2913
2841
  function toTextRange(positionOrRange) {
2914
2842
  return typeof positionOrRange === "number" ? { end: positionOrRange, pos: positionOrRange } : positionOrRange;
2915
2843
  }
@@ -3169,6 +3097,180 @@ var parseDataForExtendsClassCompletion = fn(
3169
3097
  );
3170
3098
  });
3171
3099
 
3100
+ // src/core/LSP.ts
3101
+ var RefactorNotApplicableError = class extends TaggedError("RefactorNotApplicableError") {
3102
+ };
3103
+ function createRefactor(definition) {
3104
+ return definition;
3105
+ }
3106
+ function createDiagnostic(definition) {
3107
+ return definition;
3108
+ }
3109
+ function createCompletion(definition) {
3110
+ return definition;
3111
+ }
3112
+ var PluginOptions = Tag("PluginOptions");
3113
+ var SourceFileNotFoundError = class extends TaggedError("SourceFileNotFoundError") {
3114
+ };
3115
+ var getSemanticDiagnostics = fn("LSP.getSemanticDiagnostics")(function* (diagnostics2, sourceFile) {
3116
+ const effectDiagnostics = [];
3117
+ const executor = yield* createDiagnosticExecutor(sourceFile);
3118
+ for (const diagnostic of diagnostics2) {
3119
+ const result = yield* option(executor.execute(diagnostic));
3120
+ if (isSome2(result)) {
3121
+ effectDiagnostics.push(
3122
+ ...pipe(
3123
+ result.value,
3124
+ map2((_) => ({
3125
+ file: sourceFile,
3126
+ start: _.node.getStart(sourceFile),
3127
+ length: _.node.getEnd() - _.node.getStart(sourceFile),
3128
+ messageText: _.messageText,
3129
+ category: _.category,
3130
+ code: diagnostic.code,
3131
+ source: "effect"
3132
+ }))
3133
+ )
3134
+ );
3135
+ }
3136
+ }
3137
+ return effectDiagnostics;
3138
+ });
3139
+ var getCodeFixesAtPosition = fn("LSP.getCodeFixesAtPosition")(function* (diagnostics2, sourceFile, start, end, errorCodes) {
3140
+ const runnableDiagnostics = diagnostics2.filter((_) => errorCodes.indexOf(_.code) > -1);
3141
+ const applicableFixes = [];
3142
+ const executor = yield* createDiagnosticExecutor(sourceFile);
3143
+ for (const diagnostic of runnableDiagnostics) {
3144
+ const result = yield* option(executor.execute(diagnostic));
3145
+ if (isSome2(result)) {
3146
+ applicableFixes.push(
3147
+ ...pipe(
3148
+ result.value,
3149
+ filter(
3150
+ (_) => _.node.getStart(sourceFile) === start && _.node.getEnd() === end
3151
+ ),
3152
+ map2((_) => _.fixes),
3153
+ flatten
3154
+ )
3155
+ );
3156
+ }
3157
+ }
3158
+ return applicableFixes;
3159
+ });
3160
+ var getApplicableRefactors = fn("LSP.getApplicableRefactors")(function* (refactors2, sourceFile, positionOrRange) {
3161
+ const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
3162
+ const effectRefactors = [];
3163
+ for (const refactor of refactors2) {
3164
+ const result = yield* option(refactor.apply(sourceFile, textRange));
3165
+ if (isSome2(result)) {
3166
+ effectRefactors.push({
3167
+ name: refactor.name,
3168
+ description: refactor.description,
3169
+ actions: [{
3170
+ name: refactor.name,
3171
+ description: result.value.description,
3172
+ kind: result.value.kind
3173
+ }]
3174
+ });
3175
+ }
3176
+ }
3177
+ return effectRefactors;
3178
+ });
3179
+ var getEditsForRefactor = fn("LSP.getEditsForRefactor")(function* (refactors2, sourceFile, positionOrRange, refactorName) {
3180
+ const refactor = refactors2.find((refactor2) => refactor2.name === refactorName);
3181
+ if (!refactor) {
3182
+ return yield* fail3(new RefactorNotApplicableError());
3183
+ }
3184
+ const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
3185
+ return yield* refactor.apply(sourceFile, textRange);
3186
+ });
3187
+ var getCompletionsAtPosition = fn("LSP.getCompletionsAtPosition")(function* (completions2, sourceFile, position, options, formatCodeSettings) {
3188
+ const effectCompletions = [];
3189
+ for (const completion of completions2) {
3190
+ const result = yield* completion.apply(sourceFile, position, options, formatCodeSettings);
3191
+ effectCompletions.push(
3192
+ ...result.map((_) => ({ sortText: "11", ..._ }))
3193
+ );
3194
+ }
3195
+ return effectCompletions;
3196
+ });
3197
+ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
3198
+ function* (sourceFile) {
3199
+ const ts = yield* service(TypeScriptApi);
3200
+ const ruleOverrides = {};
3201
+ const skippedRules = [];
3202
+ const regex = /@effect-diagnostics((?:\s[a-zA-Z0-9/]+:(?:off|warning|error|message|suggestion|skip-file))+)?/gm;
3203
+ let match3;
3204
+ while ((match3 = regex.exec(sourceFile.text)) !== null) {
3205
+ const rulesCaptureGroup = match3[1];
3206
+ if (rulesCaptureGroup) {
3207
+ const trimmedRuleString = rulesCaptureGroup.trim();
3208
+ if (trimmedRuleString) {
3209
+ const individualRules = trimmedRuleString.split(/\s+/);
3210
+ for (const rulePair of individualRules) {
3211
+ const [ruleName, ruleLevel] = rulePair.toLowerCase().split(":");
3212
+ if (ruleName && ruleLevel) {
3213
+ if (ruleLevel === "skip-file") skippedRules.push(ruleName);
3214
+ ruleOverrides[ruleName] = ruleOverrides[ruleName] || [];
3215
+ const newLength = ruleOverrides[ruleName].push({
3216
+ start: match3.index,
3217
+ end: Number.MAX_SAFE_INTEGER,
3218
+ level: ruleLevel
3219
+ });
3220
+ if (newLength > 1) ruleOverrides[ruleName][newLength - 2].end = match3.index;
3221
+ }
3222
+ }
3223
+ }
3224
+ }
3225
+ }
3226
+ const levelToDiagnosticCategory = {
3227
+ error: ts.DiagnosticCategory.Error,
3228
+ warning: ts.DiagnosticCategory.Warning,
3229
+ message: ts.DiagnosticCategory.Message,
3230
+ suggestion: ts.DiagnosticCategory.Suggestion
3231
+ };
3232
+ const execute = fn("LSP.ruleExecutor")(function* (rule) {
3233
+ const ruleNameLowered = rule.name.toLowerCase();
3234
+ if (skippedRules.indexOf(ruleNameLowered) > -1) return [];
3235
+ let modifiedDiagnostics = yield* rule.apply(sourceFile);
3236
+ for (const override of ruleOverrides[ruleNameLowered] || []) {
3237
+ if (override.level === "off") {
3238
+ modifiedDiagnostics = modifiedDiagnostics.filter(
3239
+ (_) => !(_.node.getStart(sourceFile) >= override.start && _.node.getEnd() <= override.end)
3240
+ );
3241
+ } else {
3242
+ for (const message of modifiedDiagnostics.filter(
3243
+ (_) => _.node.getStart(sourceFile) >= override.start && _.node.getEnd() <= override.end
3244
+ )) {
3245
+ message.category = override.level in levelToDiagnosticCategory ? levelToDiagnosticCategory[override.level] : message.category;
3246
+ }
3247
+ }
3248
+ }
3249
+ const fixByDisableEntireFile = {
3250
+ fixName: rule.name + "_skipFile",
3251
+ description: "Disable " + rule.name + " for this file",
3252
+ apply: flatMap5(
3253
+ service(ChangeTracker),
3254
+ (changeTracker) => sync(
3255
+ () => changeTracker.insertText(
3256
+ sourceFile,
3257
+ 0,
3258
+ `/** @effect-diagnostics ${rule.name}:skip-file */
3259
+ `
3260
+ )
3261
+ )
3262
+ )
3263
+ };
3264
+ const rulesWithDisableFix = modifiedDiagnostics.map((diagnostic) => ({
3265
+ ...diagnostic,
3266
+ fixes: diagnostic.fixes.concat([fixByDisableEntireFile])
3267
+ }));
3268
+ return rulesWithDisableFix;
3269
+ });
3270
+ return { execute };
3271
+ }
3272
+ );
3273
+
3172
3274
  // src/completions/contextSelfInClasses.ts
3173
3275
  var contextSelfInClasses = createCompletion({
3174
3276
  name: "effect/contextSelfInClasses",
@@ -3325,7 +3427,7 @@ var completions = [
3325
3427
  effectDataClasses
3326
3428
  ];
3327
3429
 
3328
- // src/utils/TypeCheckerApi.ts
3430
+ // src/core/TypeCheckerApi.ts
3329
3431
  var TypeCheckerApi = Tag("TypeChecker");
3330
3432
  var TypeCheckerApiCache = Tag("TypeCheckerApiCache");
3331
3433
  function makeTypeCheckerApiCache() {
@@ -3786,7 +3888,7 @@ var floatingEffect = createDiagnostic({
3786
3888
  node,
3787
3889
  category: ts.DiagnosticCategory.Error,
3788
3890
  messageText: `Effect must be yielded or assigned to a variable.`,
3789
- fix: none2()
3891
+ fixes: []
3790
3892
  });
3791
3893
  }
3792
3894
  }
@@ -3838,7 +3940,7 @@ var missingEffectContext = createDiagnostic({
3838
3940
  node,
3839
3941
  category: ts.DiagnosticCategory.Error,
3840
3942
  messageText: `Missing '${sortTypes(missingContext).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
3841
- fix: none2()
3943
+ fixes: []
3842
3944
  }
3843
3945
  );
3844
3946
  }
@@ -3890,7 +3992,7 @@ var missingEffectError = createDiagnostic({
3890
3992
  node,
3891
3993
  category: ts.DiagnosticCategory.Error,
3892
3994
  messageText: `Missing '${sortTypes(missingContext).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect errors.`,
3893
- fix: none2()
3995
+ fixes: []
3894
3996
  }
3895
3997
  );
3896
3998
  }
@@ -3947,11 +4049,11 @@ var missingStarInYieldEffectGen = createDiagnostic({
3947
4049
  node,
3948
4050
  category: ts.DiagnosticCategory.Error,
3949
4051
  messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
3950
- fix: none2()
4052
+ fixes: []
3951
4053
  })
3952
4054
  );
3953
4055
  brokenYields.forEach((node) => {
3954
- const fix = node.expression ? some2({
4056
+ const fix = node.expression ? [{
3955
4057
  fixName: "missingStarInYieldEffectGen_fix",
3956
4058
  description: "Replace yield with yield*",
3957
4059
  apply: gen2(function* () {
@@ -3965,12 +4067,12 @@ var missingStarInYieldEffectGen = createDiagnostic({
3965
4067
  )
3966
4068
  );
3967
4069
  })
3968
- }) : none2();
4070
+ }] : [];
3969
4071
  effectDiagnostics.push({
3970
4072
  node,
3971
4073
  category: ts.DiagnosticCategory.Error,
3972
4074
  messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
3973
- fix
4075
+ fixes: fix
3974
4076
  });
3975
4077
  });
3976
4078
  return effectDiagnostics;
@@ -3996,7 +4098,7 @@ var unnecessaryEffectGen = createDiagnostic({
3996
4098
  ts.forEachChild(node, appendNodeToVisit);
3997
4099
  const maybeUnnecessaryGen = yield* pipe(
3998
4100
  effectGen(node),
3999
- flatMap4(({ body }) => returnYieldEffectBlock(body)),
4101
+ flatMap5(({ body }) => returnYieldEffectBlock(body)),
4000
4102
  option
4001
4103
  );
4002
4104
  if (isSome2(maybeUnnecessaryGen)) {
@@ -4008,7 +4110,7 @@ var unnecessaryEffectGen = createDiagnostic({
4008
4110
  node,
4009
4111
  category: ts.DiagnosticCategory.Suggestion,
4010
4112
  messageText: `This Effect.gen is useless here because it only contains a single return statement.`,
4011
- fix: some2({
4113
+ fixes: [{
4012
4114
  fixName: "unnecessaryEffectGen_fix",
4013
4115
  description: "Remove the Effect.gen, and keep the body",
4014
4116
  apply: gen2(function* () {
@@ -4017,7 +4119,7 @@ var unnecessaryEffectGen = createDiagnostic({
4017
4119
  );
4018
4120
  textChanges.replaceNode(sourceFile, node, body);
4019
4121
  })
4020
- })
4122
+ }]
4021
4123
  })
4022
4124
  );
4023
4125
  return effectDiagnostics;
@@ -4499,7 +4601,7 @@ var removeUnnecessaryEffectGen = createRefactor({
4499
4601
  for (const nodeToReplace of yield* getAncestorNodesInRange(sourceFile, textRange)) {
4500
4602
  const maybeNode = yield* pipe(
4501
4603
  effectGen(nodeToReplace),
4502
- flatMap4(({ body }) => returnYieldEffectBlock(body)),
4604
+ flatMap5(({ body }) => returnYieldEffectBlock(body)),
4503
4605
  option
4504
4606
  );
4505
4607
  if (isNone2(maybeNode)) continue;