@effect/language-service 0.25.0 → 0.26.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.
package/index.js CHANGED
@@ -903,6 +903,7 @@ var NanoFiber = class {
903
903
  _stack = [];
904
904
  _yielded = void 0;
905
905
  _services = {};
906
+ _cache = {};
906
907
  runLoop(nano) {
907
908
  let current = nano;
908
909
  while (true) {
@@ -1053,8 +1054,32 @@ var service = (tag) => {
1053
1054
  nano[args] = tag;
1054
1055
  return nano;
1055
1056
  };
1056
- function cachedBy(fa, _key, _lookupKey) {
1057
- return (...args2) => fa(...args2);
1057
+ var CachedProto = {
1058
+ ...PrimitiveProto,
1059
+ [evaluate](fiber) {
1060
+ const [fa, type, key] = this[args];
1061
+ const cache = fiber._cache[type] || /* @__PURE__ */ new WeakMap();
1062
+ fiber._cache[type] = cache;
1063
+ const cached2 = cache.get(key);
1064
+ if (cached2) return cached2;
1065
+ return match2(fa, {
1066
+ onSuccess: (_) => {
1067
+ cache.set(key, succeed(_));
1068
+ return succeed(_);
1069
+ },
1070
+ onFailure: (_) => {
1071
+ cache.set(key, fail(_));
1072
+ return fail(_);
1073
+ }
1074
+ });
1075
+ }
1076
+ };
1077
+ function cachedBy(fa, type, lookupKey) {
1078
+ return (...p) => {
1079
+ const nano = Object.create(CachedProto);
1080
+ nano[args] = [fa(...p), type, lookupKey(...p)];
1081
+ return nano;
1082
+ };
1058
1083
  }
1059
1084
  var option = (fa) => {
1060
1085
  const nano = Object.create(MatchProto);
@@ -2018,8 +2043,7 @@ var unrollUnionMembers = (type) => {
2018
2043
  var appendToUniqueTypesMap = fn(
2019
2044
  "TypeCheckerApi.appendToUniqueTypesMap"
2020
2045
  )(
2021
- function* (memory, initialType, excludeNever) {
2022
- const ts = yield* service(TypeScriptApi);
2046
+ function* (memory, initialType, shouldExclude) {
2023
2047
  const typeChecker = yield* service(TypeCheckerApi);
2024
2048
  const newIndexes = /* @__PURE__ */ new Set();
2025
2049
  const knownIndexes = /* @__PURE__ */ new Set();
@@ -2027,7 +2051,7 @@ var appendToUniqueTypesMap = fn(
2027
2051
  while (toTest.length > 0) {
2028
2052
  const type = toTest.pop();
2029
2053
  if (!type) break;
2030
- if (excludeNever && type.flags & ts.TypeFlags.Never) {
2054
+ if (yield* shouldExclude(type)) {
2031
2055
  continue;
2032
2056
  }
2033
2057
  if (type.isUnion()) {
@@ -2650,11 +2674,16 @@ function make3(ts, typeChecker) {
2650
2674
  const pipeCall = cachedBy(
2651
2675
  function(node) {
2652
2676
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && node.expression.name.text === "pipe") {
2653
- return succeed({ node, subject: node.expression.expression, args: Array.from(node.arguments) });
2677
+ return succeed({
2678
+ node,
2679
+ subject: node.expression.expression,
2680
+ args: Array.from(node.arguments),
2681
+ kind: "pipeable"
2682
+ });
2654
2683
  }
2655
2684
  if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "pipe" && node.arguments.length > 0) {
2656
2685
  const [subject, ...args2] = node.arguments;
2657
- return succeed({ node, subject, args: args2 });
2686
+ return succeed({ node, subject, args: args2, kind: "pipe" });
2658
2687
  }
2659
2688
  return typeParserIssue("Node is not a pipe call", void 0, node);
2660
2689
  },
@@ -2693,6 +2722,7 @@ function make3(ts, typeChecker) {
2693
2722
  unnecessaryEffectGen: unnecessaryEffectGen2,
2694
2723
  effectSchemaType,
2695
2724
  contextTag,
2725
+ pipeableType,
2696
2726
  pipeCall,
2697
2727
  scopeType
2698
2728
  };
@@ -3014,7 +3044,18 @@ var leakingRequirements = createDiagnostic({
3014
3044
  );
3015
3045
  if (effectContextType) {
3016
3046
  effectMembers++;
3017
- const { allIndexes } = yield* appendToUniqueTypesMap(memory, effectContextType, true);
3047
+ const { allIndexes } = yield* appendToUniqueTypesMap(
3048
+ memory,
3049
+ effectContextType,
3050
+ (type) => {
3051
+ if (type.flags & ts.TypeFlags.Never) return succeed(true);
3052
+ return pipe(
3053
+ typeParser.scopeType(type, atLocation),
3054
+ map4(() => true),
3055
+ orElse2(() => succeed(false))
3056
+ );
3057
+ }
3058
+ );
3018
3059
  if (!sharedRequirementsKeys) {
3019
3060
  sharedRequirementsKeys = allIndexes;
3020
3061
  } else {
@@ -3570,8 +3611,8 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
3570
3611
  // src/diagnostics/tryCatchInEffectGen.ts
3571
3612
  var tryCatchInEffectGen = createDiagnostic({
3572
3613
  name: "tryCatchInEffectGen",
3573
- code: 12,
3574
- severity: "warning",
3614
+ code: 15,
3615
+ severity: "suggestion",
3575
3616
  apply: fn("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
3576
3617
  const ts = yield* service(TypeScriptApi);
3577
3618
  const typeParser = yield* service(TypeParser);
@@ -3700,6 +3741,80 @@ var unnecessaryPipe = createDiagnostic({
3700
3741
  })
3701
3742
  });
3702
3743
 
3744
+ // src/diagnostics/unnecessaryPipeChain.ts
3745
+ var unnecessaryPipeChain = createDiagnostic({
3746
+ name: "unnecessaryPipeChain",
3747
+ code: 16,
3748
+ severity: "suggestion",
3749
+ apply: fn("unnecessaryPipeChain.apply")(function* (sourceFile, report) {
3750
+ const ts = yield* service(TypeScriptApi);
3751
+ const typeParser = yield* service(TypeParser);
3752
+ const nodeToVisit = [];
3753
+ const appendNodeToVisit = (node) => {
3754
+ nodeToVisit.push(node);
3755
+ return void 0;
3756
+ };
3757
+ ts.forEachChild(sourceFile, appendNodeToVisit);
3758
+ while (nodeToVisit.length > 0) {
3759
+ const node = nodeToVisit.shift();
3760
+ ts.forEachChild(node, appendNodeToVisit);
3761
+ if (ts.isCallExpression(node)) {
3762
+ yield* pipe(
3763
+ typeParser.pipeCall(node),
3764
+ flatMap2(
3765
+ (pipeCall) => map4(typeParser.pipeCall(pipeCall.subject), (innerCall) => ({ pipeCall, innerCall }))
3766
+ ),
3767
+ map4(({ innerCall, pipeCall }) => {
3768
+ report({
3769
+ node,
3770
+ messageText: `Chained pipe calls can be simplified to a single pipe call`,
3771
+ fixes: [{
3772
+ fixName: "unnecessaryPipeChain_fix",
3773
+ description: "Rewrite as single pipe call",
3774
+ apply: gen(function* () {
3775
+ const changeTracker = yield* service(
3776
+ ChangeTracker
3777
+ );
3778
+ switch (innerCall.kind) {
3779
+ case "pipe": {
3780
+ changeTracker.replaceNode(
3781
+ sourceFile,
3782
+ node,
3783
+ ts.factory.createCallExpression(
3784
+ ts.factory.createIdentifier("pipe"),
3785
+ void 0,
3786
+ [innerCall.subject, ...innerCall.args, ...pipeCall.args]
3787
+ )
3788
+ );
3789
+ break;
3790
+ }
3791
+ case "pipeable": {
3792
+ changeTracker.replaceNode(
3793
+ sourceFile,
3794
+ node,
3795
+ ts.factory.createCallExpression(
3796
+ ts.factory.createPropertyAccessExpression(
3797
+ innerCall.subject,
3798
+ "pipe"
3799
+ ),
3800
+ void 0,
3801
+ [...innerCall.args, ...pipeCall.args]
3802
+ )
3803
+ );
3804
+ break;
3805
+ }
3806
+ }
3807
+ })
3808
+ }]
3809
+ });
3810
+ }),
3811
+ ignore
3812
+ );
3813
+ }
3814
+ }
3815
+ })
3816
+ });
3817
+
3703
3818
  // src/diagnostics.ts
3704
3819
  var diagnostics = [
3705
3820
  duplicatePackage,
@@ -3716,7 +3831,8 @@ var diagnostics = [
3716
3831
  tryCatchInEffectGen,
3717
3832
  importFromBarrel,
3718
3833
  scopeInLayerEffect,
3719
- effectInVoidSuccess
3834
+ effectInVoidSuccess,
3835
+ unnecessaryPipeChain
3720
3836
  ];
3721
3837
 
3722
3838
  // src/completions/effectDiagnosticsComment.ts
@@ -8796,6 +8912,7 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
8796
8912
  const ts = yield* service(TypeScriptApi);
8797
8913
  const typeChecker = yield* service(TypeCheckerApi);
8798
8914
  const typeParser = yield* service(TypeParser);
8915
+ const excludeNever = (type) => succeed((type.flags & ts.TypeFlags.Never) !== 0);
8799
8916
  const maybePipe = yield* option(typeParser.pipeCall(node));
8800
8917
  if (isSome2(maybePipe)) {
8801
8918
  let graphNode = yield* processLayerGraphNode(ctx, maybePipe.value.subject, void 0);
@@ -8815,12 +8932,12 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
8815
8932
  const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
8816
8933
  ctx.services,
8817
8934
  maybeLayer.value.ROut,
8818
- true
8935
+ excludeNever
8819
8936
  );
8820
8937
  const { allIndexes: inTypes } = yield* appendToUniqueTypesMap(
8821
8938
  ctx.services,
8822
8939
  maybeLayer.value.RIn,
8823
- true
8940
+ excludeNever
8824
8941
  );
8825
8942
  return new GraphNodeCompoundTransform(
8826
8943
  ctx.nextId(),
@@ -8844,12 +8961,12 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
8844
8961
  const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
8845
8962
  ctx.services,
8846
8963
  maybeLayer.value.ROut,
8847
- true
8964
+ excludeNever
8848
8965
  );
8849
8966
  const { allIndexes: inTypes } = yield* appendToUniqueTypesMap(
8850
8967
  ctx.services,
8851
8968
  maybeLayer.value.RIn,
8852
- true
8969
+ excludeNever
8853
8970
  );
8854
8971
  if (ts.isCallExpression(node)) {
8855
8972
  const argNodes = yield* option(
@@ -8894,12 +9011,12 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
8894
9011
  const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
8895
9012
  ctx.services,
8896
9013
  maybeLayer.value.ROut,
8897
- true
9014
+ excludeNever
8898
9015
  );
8899
9016
  const { allIndexes: inTypes } = yield* appendToUniqueTypesMap(
8900
9017
  ctx.services,
8901
9018
  maybeLayer.value.RIn,
8902
- true
9019
+ excludeNever
8903
9020
  );
8904
9021
  return new GraphNodeLeaf(ctx.nextId(), node, outTypes, inTypes);
8905
9022
  }
@@ -9892,6 +10009,66 @@ var toggleLazyConst = createRefactor({
9892
10009
  })
9893
10010
  });
9894
10011
 
10012
+ // src/refactors/togglePipeStyle.ts
10013
+ var togglePipeStyle = createRefactor({
10014
+ name: "togglePipeStyle",
10015
+ description: "Toggle pipe style",
10016
+ apply: fn("togglePipeStyle.apply")(function* (sourceFile, textRange) {
10017
+ const ts = yield* service(TypeScriptApi);
10018
+ const typeChecker = yield* service(TypeCheckerApi);
10019
+ const typeParser = yield* service(TypeParser);
10020
+ const togglePipeStyle2 = (node) => gen(function* () {
10021
+ const pipeCall = yield* typeParser.pipeCall(node);
10022
+ switch (pipeCall.kind) {
10023
+ case "pipe": {
10024
+ yield* typeParser.pipeableType(typeChecker.getTypeAtLocation(pipeCall.subject), pipeCall.subject);
10025
+ return {
10026
+ kind: "refactor.rewrite.effect.togglePipeStyle",
10027
+ description: "Rewrite as X.pipe(Y, Z, ...)",
10028
+ apply: gen(function* () {
10029
+ const changeTracker = yield* service(ChangeTracker);
10030
+ changeTracker.replaceNode(
10031
+ sourceFile,
10032
+ node,
10033
+ ts.factory.createCallExpression(
10034
+ ts.factory.createPropertyAccessExpression(
10035
+ pipeCall.subject,
10036
+ "pipe"
10037
+ ),
10038
+ void 0,
10039
+ pipeCall.args
10040
+ )
10041
+ );
10042
+ })
10043
+ };
10044
+ }
10045
+ case "pipeable":
10046
+ return {
10047
+ kind: "refactor.rewrite.effect.togglePipeStyle",
10048
+ description: "Rewrite as pipe(X, Y, Z, ...)",
10049
+ apply: gen(function* () {
10050
+ const changeTracker = yield* service(ChangeTracker);
10051
+ changeTracker.replaceNode(
10052
+ sourceFile,
10053
+ node,
10054
+ ts.factory.createCallExpression(
10055
+ ts.factory.createIdentifier("pipe"),
10056
+ void 0,
10057
+ [pipeCall.subject].concat(pipeCall.args)
10058
+ )
10059
+ );
10060
+ })
10061
+ };
10062
+ }
10063
+ });
10064
+ const ancestorNodes = yield* getAncestorNodesInRange(sourceFile, textRange);
10065
+ return yield* pipe(
10066
+ firstSuccessOf(ancestorNodes.map(togglePipeStyle2)),
10067
+ orElse2(() => fail(new RefactorNotApplicableError()))
10068
+ );
10069
+ })
10070
+ });
10071
+
9895
10072
  // src/refactors/toggleReturnTypeAnnotation.ts
9896
10073
  var toggleReturnTypeAnnotation = createRefactor({
9897
10074
  name: "toggleReturnTypeAnnotation",
@@ -10608,7 +10785,8 @@ var refactors = [
10608
10785
  toggleTypeAnnotation,
10609
10786
  wrapWithEffectGen,
10610
10787
  wrapWithPipe,
10611
- effectGenToFn
10788
+ effectGenToFn,
10789
+ togglePipeStyle
10612
10790
  ];
10613
10791
 
10614
10792
  // src/index.ts