@effect/language-service 0.8.0 → 0.8.1

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 +160 -17
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -954,6 +954,18 @@ var sort = /* @__PURE__ */ dual(2, (self, O) => {
954
954
  });
955
955
  var empty = () => [];
956
956
  var map2 = /* @__PURE__ */ dual(2, (self, f) => self.map(f));
957
+ var filterMap = /* @__PURE__ */ dual(2, (self, f) => {
958
+ const as = fromIterable(self);
959
+ 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
+ }
965
+ }
966
+ return out;
967
+ });
968
+ var getSomes = /* @__PURE__ */ filterMap(identity);
957
969
  var filter = /* @__PURE__ */ dual(2, (self, predicate) => {
958
970
  const as = fromIterable(self);
959
971
  const out = [];
@@ -2789,6 +2801,28 @@ function getSemanticDiagnostics(diagnostics2, sourceFile) {
2789
2801
  return effectDiagnostics;
2790
2802
  });
2791
2803
  }
2804
+ function getCodeFixesAtPosition(diagnostics2, sourceFile, start, end, errorCodes) {
2805
+ return gen2(function* () {
2806
+ const runnableDiagnostics = diagnostics2.filter((_) => errorCodes.indexOf(_.code) > -1);
2807
+ const applicableFixes = [];
2808
+ for (const diagnostic of runnableDiagnostics) {
2809
+ const result = yield* option(diagnostic.apply(sourceFile));
2810
+ if (isSome2(result)) {
2811
+ applicableFixes.push(
2812
+ ...pipe(
2813
+ result.value,
2814
+ filter(
2815
+ (_) => _.node.getStart(sourceFile) === start && _.node.getEnd() === end
2816
+ ),
2817
+ map2((_) => _.fix),
2818
+ getSomes
2819
+ )
2820
+ );
2821
+ }
2822
+ }
2823
+ return applicableFixes;
2824
+ });
2825
+ }
2792
2826
  function getApplicableRefactors(refactors2, sourceFile, positionOrRange) {
2793
2827
  return gen2(function* () {
2794
2828
  const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
@@ -3270,7 +3304,8 @@ var floatingEffect = createDiagnostic({
3270
3304
  effectDiagnostics.push({
3271
3305
  node,
3272
3306
  category: ts.DiagnosticCategory.Error,
3273
- messageText: `Effect must be yielded or assigned to a variable.`
3307
+ messageText: `Effect must be yielded or assigned to a variable.`,
3308
+ fix: none2()
3274
3309
  });
3275
3310
  }
3276
3311
  }
@@ -3330,7 +3365,8 @@ var missingEffectContext = createDiagnostic({
3330
3365
  {
3331
3366
  node: node2,
3332
3367
  category: ts.DiagnosticCategory.Error,
3333
- messageText: `Missing '${sortTypes(missingContext).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`
3368
+ messageText: `Missing '${sortTypes(missingContext).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
3369
+ fix: none2()
3334
3370
  }
3335
3371
  );
3336
3372
  }
@@ -3391,7 +3427,8 @@ var missingEffectError = createDiagnostic({
3391
3427
  {
3392
3428
  node: node2,
3393
3429
  category: ts.DiagnosticCategory.Error,
3394
- messageText: `Missing '${sortTypes(missingContext).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect errors.`
3430
+ messageText: `Missing '${sortTypes(missingContext).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect errors.`,
3431
+ fix: none2()
3395
3432
  }
3396
3433
  );
3397
3434
  }
@@ -3448,16 +3485,33 @@ var missingStarInYieldEffectGen = createDiagnostic({
3448
3485
  (node) => effectDiagnostics.push({
3449
3486
  node,
3450
3487
  category: ts.DiagnosticCategory.Error,
3451
- messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`
3488
+ messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
3489
+ fix: none2()
3452
3490
  })
3453
3491
  );
3454
- brokenYields.forEach(
3455
- (node) => effectDiagnostics.push({
3492
+ brokenYields.forEach((node) => {
3493
+ const fix = node.expression ? some2({
3494
+ fixName: "missingStarInYieldEffectGen_fix",
3495
+ description: "Replace yield with yield*",
3496
+ apply: gen2(function* () {
3497
+ const changeTracker = yield* service(ChangeTracker);
3498
+ changeTracker.replaceNode(
3499
+ sourceFile,
3500
+ node,
3501
+ ts.factory.createYieldExpression(
3502
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
3503
+ node.expression
3504
+ )
3505
+ );
3506
+ })
3507
+ }) : none2();
3508
+ effectDiagnostics.push({
3456
3509
  node,
3457
3510
  category: ts.DiagnosticCategory.Error,
3458
- messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`
3459
- })
3460
- );
3511
+ messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
3512
+ fix
3513
+ });
3514
+ });
3461
3515
  return effectDiagnostics;
3462
3516
  })
3463
3517
  });
@@ -3469,7 +3523,7 @@ var unnecessaryEffectGen = createDiagnostic({
3469
3523
  apply: (sourceFile) => gen2(function* () {
3470
3524
  const ts = yield* service(TypeScriptApi);
3471
3525
  const effectDiagnostics = [];
3472
- const brokenGenerators = /* @__PURE__ */ new Set();
3526
+ const unnecessaryGenerators = /* @__PURE__ */ new Map();
3473
3527
  const nodeToVisit = [];
3474
3528
  const appendNodeToVisit = (node) => {
3475
3529
  nodeToVisit.push(node);
@@ -3485,14 +3539,24 @@ var unnecessaryEffectGen = createDiagnostic({
3485
3539
  option
3486
3540
  );
3487
3541
  if (isSome2(maybeUnnecessaryGen)) {
3488
- brokenGenerators.add(node);
3542
+ unnecessaryGenerators.set(node, maybeUnnecessaryGen.value);
3489
3543
  }
3490
3544
  }
3491
- brokenGenerators.forEach(
3492
- (node) => effectDiagnostics.push({
3545
+ unnecessaryGenerators.forEach(
3546
+ (body, node) => effectDiagnostics.push({
3493
3547
  node,
3494
3548
  category: ts.DiagnosticCategory.Suggestion,
3495
- messageText: `This Effect.gen is useless here because it only contains a single return statement.`
3549
+ messageText: `This Effect.gen is useless here because it only contains a single return statement.`,
3550
+ fix: some2({
3551
+ fixName: "unnecessaryEffectGen_fix",
3552
+ description: "Remove the Effect.gen, and keep the body",
3553
+ apply: gen2(function* () {
3554
+ const textChanges = yield* service(
3555
+ ChangeTracker
3556
+ );
3557
+ textChanges.replaceNode(sourceFile, node, body);
3558
+ })
3559
+ })
3496
3560
  })
3497
3561
  );
3498
3562
  return effectDiagnostics;
@@ -3677,10 +3741,17 @@ function findImportedModuleIdentifier(sourceFile, test) {
3677
3741
  const namedBindings = importClause.namedBindings;
3678
3742
  if (!namedBindings) continue;
3679
3743
  if (ts.isNamespaceImport(namedBindings)) {
3680
- if (yield* test(namedBindings.name)) return namedBindings.name;
3744
+ if (yield* test(namedBindings.name, statement.moduleSpecifier, none2())) {
3745
+ return namedBindings.name;
3746
+ }
3681
3747
  } else if (ts.isNamedImports(namedBindings)) {
3682
3748
  for (const importSpecifier of namedBindings.elements) {
3683
- if (yield* test(importSpecifier.name)) return importSpecifier.name;
3749
+ const importProperty = fromNullable2(importSpecifier.propertyName).pipe(
3750
+ orElse2(() => some2(importSpecifier.name))
3751
+ );
3752
+ if (yield* test(importSpecifier.name, statement.moduleSpecifier, importProperty)) {
3753
+ return importSpecifier.name;
3754
+ }
3684
3755
  }
3685
3756
  }
3686
3757
  }
@@ -4430,9 +4501,81 @@ var init = (modules) => {
4430
4501
  quickinfo: info.config && "quickinfo" in info.config && typeof info.config.quickinfo === "boolean" ? info.config.quickinfo : true
4431
4502
  };
4432
4503
  const proxy = /* @__PURE__ */ Object.create(null);
4433
- for (const k of Object.keys(info.languageService)) {
4504
+ for (const k of Object.keys(languageService)) {
4434
4505
  proxy[k] = (...args) => languageService[k].apply(languageService, args);
4435
4506
  }
4507
+ const diagnosticsErrorCodes = diagnostics.map((diagnostic) => diagnostic.code);
4508
+ try {
4509
+ ;
4510
+ modules.typescript.codefix.registerCodeFix({
4511
+ errorCodes: diagnosticsErrorCodes,
4512
+ getCodeActions: () => void 0
4513
+ });
4514
+ } catch (_) {
4515
+ }
4516
+ proxy.getSupportedCodeFixes = (...args) => languageService.getSupportedCodeFixes(...args).concat(
4517
+ diagnosticsErrorCodes.map((_) => "" + _)
4518
+ );
4519
+ proxy.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences, ...args) => {
4520
+ const applicableCodeFixes = languageService.getCodeFixesAtPosition(
4521
+ fileName,
4522
+ start,
4523
+ end,
4524
+ errorCodes,
4525
+ formatOptions,
4526
+ preferences,
4527
+ ...args
4528
+ );
4529
+ const program = languageService.getProgram();
4530
+ if (program) {
4531
+ const sourceFile = program.getSourceFile(fileName);
4532
+ if (sourceFile) {
4533
+ return pipe(
4534
+ gen2(function* () {
4535
+ const effectCodeFixes = [];
4536
+ const applicableFixes = yield* getCodeFixesAtPosition(
4537
+ diagnostics,
4538
+ sourceFile,
4539
+ start,
4540
+ end,
4541
+ errorCodes
4542
+ );
4543
+ const formatContext = modules.typescript.formatting.getFormatContext(
4544
+ formatOptions,
4545
+ info.languageServiceHost
4546
+ );
4547
+ for (const applicableFix of applicableFixes) {
4548
+ const changes = modules.typescript.textChanges.ChangeTracker.with(
4549
+ {
4550
+ formatContext,
4551
+ host: info.languageServiceHost,
4552
+ preferences: preferences || {}
4553
+ },
4554
+ (changeTracker) => pipe(
4555
+ applicableFix.apply,
4556
+ provideService(ChangeTracker, changeTracker),
4557
+ run
4558
+ )
4559
+ );
4560
+ effectCodeFixes.push({
4561
+ fixName: applicableFix.fixName,
4562
+ description: applicableFix.description,
4563
+ changes
4564
+ });
4565
+ }
4566
+ return effectCodeFixes;
4567
+ }),
4568
+ provideService(TypeScriptApi, modules.typescript),
4569
+ provideService(TypeCheckerApi, program.getTypeChecker()),
4570
+ provideService(PluginOptions, pluginOptions),
4571
+ run,
4572
+ Either_exports.map((effectCodeFixes) => applicableCodeFixes.concat(effectCodeFixes)),
4573
+ Either_exports.getOrElse(() => applicableCodeFixes)
4574
+ );
4575
+ }
4576
+ }
4577
+ return applicableCodeFixes;
4578
+ };
4436
4579
  proxy.getSemanticDiagnostics = (fileName, ...args) => {
4437
4580
  const applicableDiagnostics = languageService.getSemanticDiagnostics(fileName, ...args);
4438
4581
  const program = languageService.getProgram();