@effect/language-service 0.16.6 → 0.17.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/README.md CHANGED
@@ -45,6 +45,7 @@ And you're done! You'll now be able to use a set of refactor and diagnostics tha
45
45
  ### Completions
46
46
 
47
47
  - Autocomplete 'Self' in Effect.Service, Context.Tag, Schema.TaggedClass, Schema.TaggedRequest and family
48
+ - Autocomplete Effect.gen with `function*(){}`
48
49
 
49
50
  ### Refactors
50
51
 
package/index.js CHANGED
@@ -1372,50 +1372,62 @@ var tryPreserveDeclarationSemantics = fn("AST.tryPreserveDeclarationSemantics")(
1372
1372
  return node;
1373
1373
  }
1374
1374
  );
1375
+ var parseAccessedExpressionForCompletion = fn(
1376
+ "AST.parseAccessedExpressionForCompletion"
1377
+ )(
1378
+ function* (sourceFile, position) {
1379
+ const ts = yield* service(TypeScriptApi);
1380
+ const precedingToken = ts.findPrecedingToken(position, sourceFile, void 0, true);
1381
+ if (!precedingToken) return yield* fail(new NodeNotFoundError());
1382
+ let accessedObject = precedingToken;
1383
+ let replacementSpan = ts.createTextSpan(position, 0);
1384
+ let outerNode = precedingToken;
1385
+ if (ts.isIdentifier(precedingToken) && precedingToken.parent && ts.isPropertyAccessExpression(precedingToken.parent)) {
1386
+ replacementSpan = ts.createTextSpan(
1387
+ precedingToken.parent.getStart(sourceFile),
1388
+ precedingToken.end - precedingToken.parent.getStart(sourceFile)
1389
+ );
1390
+ accessedObject = precedingToken.parent.expression;
1391
+ outerNode = precedingToken.parent;
1392
+ } else if (ts.isToken(precedingToken) && precedingToken.kind === ts.SyntaxKind.DotToken && ts.isPropertyAccessExpression(precedingToken.parent)) {
1393
+ replacementSpan = ts.createTextSpan(
1394
+ precedingToken.parent.getStart(sourceFile),
1395
+ precedingToken.end - precedingToken.parent.getStart(sourceFile)
1396
+ );
1397
+ accessedObject = precedingToken.parent.expression;
1398
+ outerNode = precedingToken.parent;
1399
+ } else if (ts.isIdentifier(precedingToken) && precedingToken.parent) {
1400
+ replacementSpan = ts.createTextSpan(
1401
+ precedingToken.getStart(sourceFile),
1402
+ precedingToken.end - precedingToken.getStart(sourceFile)
1403
+ );
1404
+ accessedObject = precedingToken;
1405
+ outerNode = precedingToken;
1406
+ } else {
1407
+ return yield* fail(new NodeNotFoundError());
1408
+ }
1409
+ return { accessedObject, outerNode, replacementSpan };
1410
+ }
1411
+ );
1375
1412
  var parseDataForExtendsClassCompletion = fn(
1376
1413
  "AST.parseDataForExtendsClassCompletion"
1377
1414
  )(function* (sourceFile, position) {
1378
1415
  const ts = yield* service(TypeScriptApi);
1379
- const precedingToken = ts.findPrecedingToken(position, sourceFile, void 0, true);
1380
- if (!precedingToken) return none2();
1381
- let accessedObject = precedingToken;
1382
- let replacementSpan = ts.createTextSpan(position, 0);
1383
- let outerNode = precedingToken;
1384
- if (ts.isIdentifier(precedingToken) && precedingToken.parent && ts.isPropertyAccessExpression(precedingToken.parent)) {
1385
- replacementSpan = ts.createTextSpan(
1386
- precedingToken.parent.getStart(sourceFile),
1387
- precedingToken.end - precedingToken.parent.getStart(sourceFile)
1388
- );
1389
- accessedObject = precedingToken.parent.expression;
1390
- outerNode = precedingToken.parent;
1391
- } else if (ts.isToken(precedingToken) && precedingToken.kind === ts.SyntaxKind.DotToken && ts.isPropertyAccessExpression(precedingToken.parent)) {
1392
- replacementSpan = ts.createTextSpan(
1393
- precedingToken.parent.getStart(sourceFile),
1394
- precedingToken.end - precedingToken.parent.getStart(sourceFile)
1395
- );
1396
- accessedObject = precedingToken.parent.expression;
1397
- outerNode = precedingToken.parent;
1398
- } else if (ts.isIdentifier(precedingToken) && precedingToken.parent) {
1399
- replacementSpan = ts.createTextSpan(
1400
- precedingToken.getStart(sourceFile),
1401
- precedingToken.end - precedingToken.getStart(sourceFile)
1402
- );
1403
- accessedObject = precedingToken;
1404
- outerNode = precedingToken;
1405
- } else {
1406
- return none2();
1407
- }
1408
- if (!ts.isIdentifier(accessedObject)) return none2();
1416
+ const { accessedObject, outerNode, replacementSpan } = yield* parseAccessedExpressionForCompletion(sourceFile, position);
1417
+ if (!ts.isIdentifier(accessedObject)) return yield* fail(new NodeNotFoundError());
1409
1418
  let classDeclaration = outerNode.parent;
1410
1419
  while (ts.isExpressionWithTypeArguments(classDeclaration) || ts.isHeritageClause(classDeclaration)) {
1411
1420
  if (!classDeclaration.parent) break;
1412
1421
  classDeclaration = classDeclaration.parent;
1413
1422
  }
1414
- if (!ts.isClassDeclaration(classDeclaration)) return none2();
1415
- if (!classDeclaration.name) return none2();
1416
- return some2(
1417
- { accessedObject, classDeclaration, className: classDeclaration.name, replacementSpan }
1418
- );
1423
+ if (!ts.isClassDeclaration(classDeclaration)) return yield* fail(new NodeNotFoundError());
1424
+ if (!classDeclaration.name) return yield* fail(new NodeNotFoundError());
1425
+ return {
1426
+ accessedObject,
1427
+ classDeclaration,
1428
+ className: classDeclaration.name,
1429
+ replacementSpan
1430
+ };
1419
1431
  });
1420
1432
  var createEffectGenCallExpression = fn("AST.createEffectGenCallExpression")(function* (effectModuleIdentifierName, node) {
1421
1433
  const ts = yield* service(TypeScriptApi);
@@ -1647,7 +1659,9 @@ var contextSelfInClasses = createCompletion({
1647
1659
  name: "effect/contextSelfInClasses",
1648
1660
  apply: fn("contextSelfInClasses")(function* (sourceFile, position) {
1649
1661
  const ts = yield* service(TypeScriptApi);
1650
- const maybeInfos = yield* parseDataForExtendsClassCompletion(sourceFile, position);
1662
+ const maybeInfos = yield* option(
1663
+ parseDataForExtendsClassCompletion(sourceFile, position)
1664
+ );
1651
1665
  if (isNone2(maybeInfos)) return [];
1652
1666
  const { accessedObject, className, replacementSpan } = maybeInfos.value;
1653
1667
  const contextName = yield* option(
@@ -1678,7 +1692,9 @@ var effectDataClasses = createCompletion({
1678
1692
  name: "effect/effectDataClasses",
1679
1693
  apply: fn("effectDataClasses")(function* (sourceFile, position) {
1680
1694
  const ts = yield* service(TypeScriptApi);
1681
- const maybeInfos = yield* parseDataForExtendsClassCompletion(sourceFile, position);
1695
+ const maybeInfos = yield* option(
1696
+ parseDataForExtendsClassCompletion(sourceFile, position)
1697
+ );
1682
1698
  if (isNone2(maybeInfos)) return [];
1683
1699
  const { accessedObject, className, replacementSpan } = maybeInfos.value;
1684
1700
  const dataName = yield* option(
@@ -1715,7 +1731,9 @@ var effectSchemaSelfInClasses = createCompletion({
1715
1731
  name: "effect/effectSchemaSelfInClasses",
1716
1732
  apply: fn("effectSchemaSelfInClasses")(function* (sourceFile, position) {
1717
1733
  const ts = yield* service(TypeScriptApi);
1718
- const maybeInfos = yield* parseDataForExtendsClassCompletion(sourceFile, position);
1734
+ const maybeInfos = yield* option(
1735
+ parseDataForExtendsClassCompletion(sourceFile, position)
1736
+ );
1719
1737
  if (isNone2(maybeInfos)) return [];
1720
1738
  const { accessedObject, className, replacementSpan } = maybeInfos.value;
1721
1739
  const effectSchemaName = yield* option(
@@ -1764,7 +1782,9 @@ var effectSelfInClasses = createCompletion({
1764
1782
  name: "effect/effectSelfInClasses",
1765
1783
  apply: fn("effectSelfInClasses")(function* (sourceFile, position) {
1766
1784
  const ts = yield* service(TypeScriptApi);
1767
- const maybeInfos = yield* parseDataForExtendsClassCompletion(sourceFile, position);
1785
+ const maybeInfos = yield* option(
1786
+ parseDataForExtendsClassCompletion(sourceFile, position)
1787
+ );
1768
1788
  if (isNone2(maybeInfos)) return [];
1769
1789
  const { accessedObject, className, replacementSpan } = maybeInfos.value;
1770
1790
  const effectName = yield* option(
@@ -1790,14 +1810,6 @@ var effectSelfInClasses = createCompletion({
1790
1810
  })
1791
1811
  });
1792
1812
 
1793
- // src/completions.ts
1794
- var completions = [
1795
- effectSchemaSelfInClasses,
1796
- effectSelfInClasses,
1797
- contextSelfInClasses,
1798
- effectDataClasses
1799
- ];
1800
-
1801
1813
  // src/core/TypeCheckerApi.ts
1802
1814
  var TypeCheckerApi = Tag("TypeChecker");
1803
1815
  var TypeCheckerApiCache = Tag("TypeCheckerApiCache");
@@ -2004,6 +2016,45 @@ var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (so
2004
2016
  return result;
2005
2017
  });
2006
2018
 
2019
+ // src/completions/genFunctionStar.ts
2020
+ var genFunctionStar = createCompletion({
2021
+ name: "effect/genFunctionStar",
2022
+ apply: fn("genFunctionStar")(function* (sourceFile, position) {
2023
+ const ts = yield* service(TypeScriptApi);
2024
+ const typeChecker = yield* service(TypeCheckerApi);
2025
+ const maybeInfos = yield* option(
2026
+ parseAccessedExpressionForCompletion(sourceFile, position)
2027
+ );
2028
+ if (isNone2(maybeInfos)) return [];
2029
+ const { accessedObject } = maybeInfos.value;
2030
+ const type = typeChecker.getTypeAtLocation(accessedObject);
2031
+ const genMemberSymbol = type.getProperty("gen");
2032
+ if (!genMemberSymbol) return [];
2033
+ const genType = typeChecker.getTypeOfSymbolAtLocation(genMemberSymbol, accessedObject);
2034
+ if (genType.getCallSignatures().length === 0) return [];
2035
+ const span = ts.createTextSpan(
2036
+ accessedObject.end + 1,
2037
+ Math.max(0, position - accessedObject.end - 1)
2038
+ );
2039
+ return [{
2040
+ name: `gen(function*(){})`,
2041
+ kind: ts.ScriptElementKind.constElement,
2042
+ insertText: `gen(function*(){${"${0}"}})`,
2043
+ replacementSpan: span,
2044
+ isSnippet: true
2045
+ }];
2046
+ })
2047
+ });
2048
+
2049
+ // src/completions.ts
2050
+ var completions = [
2051
+ effectSchemaSelfInClasses,
2052
+ effectSelfInClasses,
2053
+ contextSelfInClasses,
2054
+ genFunctionStar,
2055
+ effectDataClasses
2056
+ ];
2057
+
2007
2058
  // src/utils/TypeParser.ts
2008
2059
  var TypeParserIssue = class {
2009
2060
  constructor(type, node, message) {
@@ -3707,7 +3758,7 @@ var createUnsupportedNodeComment = (ts, sourceFile, node) => ts.addSyntheticTrai
3707
3758
  ts.SyntaxKind.MultiLineCommentTrivia,
3708
3759
  " Not supported conversion: " + node.getText(sourceFile) + " "
3709
3760
  );
3710
- var processNode = (node) => gen2(function* () {
3761
+ var processNode = (node, isVirtualTypeNode) => gen2(function* () {
3711
3762
  const { createApiCall, createApiPropertyAccess, entityNameToDataTypeName, sourceFile, ts } = yield* service(
3712
3763
  SchemaGenContext
3713
3764
  );
@@ -3741,12 +3792,12 @@ var processNode = (node) => gen2(function* () {
3741
3792
  if (ts.isUnionTypeNode(node)) {
3742
3793
  const allLiterals = yield* option(parseAllLiterals(node));
3743
3794
  if (isSome2(allLiterals)) return createApiCall("Literal", allLiterals.value);
3744
- const members = yield* all2(...node.types.map((_) => processNode(_)));
3795
+ const members = yield* all2(...node.types.map((_) => processNode(_, isVirtualTypeNode)));
3745
3796
  return createApiCall("Union", members);
3746
3797
  }
3747
3798
  if (ts.isIntersectionTypeNode(node)) {
3748
3799
  const [firstSchema, ...otherSchemas] = yield* all2(
3749
- ...node.types.map((_) => processNode(_))
3800
+ ...node.types.map((_) => processNode(_, isVirtualTypeNode))
3750
3801
  );
3751
3802
  if (otherSchemas.length === 0) return firstSchema;
3752
3803
  return ts.factory.createCallExpression(
@@ -3760,22 +3811,28 @@ var processNode = (node) => gen2(function* () {
3760
3811
  }
3761
3812
  if (ts.isTypeOperatorNode(node)) {
3762
3813
  if (node.operator === ts.SyntaxKind.KeyOfKeyword) {
3763
- return createApiCall("keyof", [yield* processNode(node.type)]);
3814
+ return createApiCall("keyof", [yield* processNode(node.type, isVirtualTypeNode)]);
3764
3815
  } else if (node.operator === ts.SyntaxKind.ReadonlyKeyword) {
3765
- return yield* processNode(node.type);
3816
+ return yield* processNode(node.type, isVirtualTypeNode);
3766
3817
  }
3767
3818
  }
3768
3819
  if (ts.isArrayTypeNode(node)) {
3769
- const typeSchema = yield* processNode(node.elementType);
3820
+ const typeSchema = yield* processNode(node.elementType, isVirtualTypeNode);
3770
3821
  return createApiCall("Array", [typeSchema]);
3771
3822
  }
3772
3823
  if (ts.isTypeLiteralNode(node)) {
3773
- const { properties, records } = yield* processMembers(node.members);
3824
+ const { properties, records } = yield* processMembers(node.members, isVirtualTypeNode);
3774
3825
  return createApiCall(
3775
3826
  "Struct",
3776
3827
  [ts.factory.createObjectLiteralExpression(properties, true)].concat(records)
3777
3828
  );
3778
3829
  }
3830
+ if (ts.isTypeQueryNode(node)) {
3831
+ const typeChecker = yield* service(TypeCheckerApi);
3832
+ const type = typeChecker.getTypeAtLocation(node.exprName);
3833
+ const typeNode = typeChecker.typeToTypeNode(type, void 0, ts.NodeBuilderFlags.NoTruncation);
3834
+ if (typeNode) return yield* processNode(typeNode, true);
3835
+ }
3779
3836
  if (ts.isTypeReferenceNode(node)) {
3780
3837
  const parsedName = entityNameToDataTypeName(node.typeName);
3781
3838
  if (isSome2(parsedName)) {
@@ -3787,13 +3844,13 @@ var processNode = (node) => gen2(function* () {
3787
3844
  case "Chunk":
3788
3845
  case "Array": {
3789
3846
  const elements = yield* all2(
3790
- ...node.typeArguments ? node.typeArguments.map(processNode) : []
3847
+ ...node.typeArguments ? node.typeArguments.map((_) => processNode(_, isVirtualTypeNode)) : []
3791
3848
  );
3792
3849
  return createApiCall(parsedName.value, elements);
3793
3850
  }
3794
3851
  case "Record": {
3795
3852
  const elements = yield* all2(
3796
- ...node.typeArguments ? node.typeArguments.map(processNode) : []
3853
+ ...node.typeArguments ? node.typeArguments.map((_) => processNode(_, isVirtualTypeNode)) : []
3797
3854
  );
3798
3855
  if (elements.length >= 2) {
3799
3856
  return createApiCall(parsedName.value, [
@@ -3807,7 +3864,7 @@ var processNode = (node) => gen2(function* () {
3807
3864
  }
3808
3865
  case "Either": {
3809
3866
  const elements = yield* all2(
3810
- ...node.typeArguments ? node.typeArguments.map(processNode) : []
3867
+ ...node.typeArguments ? node.typeArguments.map((_) => processNode(_, isVirtualTypeNode)) : []
3811
3868
  );
3812
3869
  if (elements.length >= 2) {
3813
3870
  return createApiCall(parsedName.value, [
@@ -3825,7 +3882,7 @@ var processNode = (node) => gen2(function* () {
3825
3882
  if (typeArguments.length !== 2) {
3826
3883
  return createUnsupportedNodeComment(ts, sourceFile, node);
3827
3884
  }
3828
- const baseType = yield* processNode(typeArguments[0]);
3885
+ const baseType = yield* processNode(typeArguments[0], isVirtualTypeNode);
3829
3886
  const stringLiteralArguments = yield* option(parseAllLiterals(typeArguments[1]));
3830
3887
  if (isNone2(stringLiteralArguments)) {
3831
3888
  return createUnsupportedNodeComment(ts, sourceFile, node);
@@ -3852,7 +3909,7 @@ var processNode = (node) => gen2(function* () {
3852
3909
  var processMembers = fn(
3853
3910
  "SchemaGen.processMembers"
3854
3911
  )(
3855
- function* (members) {
3912
+ function* (members, isVirtualTypeNode) {
3856
3913
  const { createApiCall, ts } = yield* service(
3857
3914
  SchemaGenContext
3858
3915
  );
@@ -3866,7 +3923,7 @@ var processMembers = fn(
3866
3923
  return yield* fail(new RequiredExplicitTypesError(propertySignature));
3867
3924
  }
3868
3925
  const propertyAssignment = pipe(
3869
- yield* processNode(propertySignature.type),
3926
+ yield* processNode(propertySignature.type, isVirtualTypeNode),
3870
3927
  propertySignature.questionToken ? (_) => createApiCall("optional", [_]) : identity,
3871
3928
  (_) => ts.factory.createPropertyAssignment(name, _)
3872
3929
  );
@@ -3880,8 +3937,8 @@ var processMembers = fn(
3880
3937
  const parameter = indexSignature.parameters[0];
3881
3938
  if (!parameter.type) return yield* fail(new RequiredExplicitTypesError(parameter));
3882
3939
  const parameterType = parameter.type;
3883
- const key = yield* processNode(parameterType);
3884
- const value = yield* processNode(indexSignature.type);
3940
+ const key = yield* processNode(parameterType, isVirtualTypeNode);
3941
+ const value = yield* processNode(indexSignature.type, isVirtualTypeNode);
3885
3942
  records.push(
3886
3943
  ts.factory.createObjectLiteralExpression([
3887
3944
  ts.factory.createPropertyAssignment("key", key),
@@ -3900,7 +3957,7 @@ var processInterfaceDeclaration = fn("SchemaGen.processInterfaceDeclaration")(
3900
3957
  const { createApiCall, ts } = yield* service(
3901
3958
  SchemaGenContext
3902
3959
  );
3903
- const { properties, records } = yield* processMembers(node.members);
3960
+ const { properties, records } = yield* processMembers(node.members, false);
3904
3961
  if (preferClass && records.length === 0) {
3905
3962
  return yield* createExportSchemaClassDeclaration(node.name.text, properties);
3906
3963
  }
@@ -3918,12 +3975,12 @@ var processTypeAliasDeclaration = fn("SchemaGen.processInterfaceDeclaration")(
3918
3975
  return yield* fail(new TypeParametersNotSupportedError(node));
3919
3976
  }
3920
3977
  if (preferClass && ts.isTypeLiteralNode(node.type)) {
3921
- const { properties, records } = yield* processMembers(node.type.members);
3978
+ const { properties, records } = yield* processMembers(node.type.members, false);
3922
3979
  if (records.length === 0) {
3923
3980
  return yield* createExportSchemaClassDeclaration(node.name.text, properties);
3924
3981
  }
3925
3982
  }
3926
- const effectSchema = yield* processNode(node.type);
3983
+ const effectSchema = yield* processNode(node.type, false);
3927
3984
  return yield* createExportVariableDeclaration(node.name.text, effectSchema);
3928
3985
  }
3929
3986
  );
@@ -4026,6 +4083,7 @@ var typeToEffectSchema = createRefactor({
4026
4083
  description: "Refactor to Schema",
4027
4084
  apply: fn("typeToEffectSchema.apply")(function* (sourceFile, textRange) {
4028
4085
  const ts = yield* service(TypeScriptApi);
4086
+ const typeChecker = yield* service(TypeCheckerApi);
4029
4087
  const maybeNode = yield* findNodeToProcess(sourceFile, textRange);
4030
4088
  if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
4031
4089
  const node = maybeNode.value;
@@ -4034,6 +4092,7 @@ var typeToEffectSchema = createRefactor({
4034
4092
  description: "Refactor to Schema",
4035
4093
  apply: pipe(
4036
4094
  applyAtNode(sourceFile, node, false),
4095
+ provideService(TypeCheckerApi, typeChecker),
4037
4096
  provideService(TypeScriptApi, ts)
4038
4097
  )
4039
4098
  };
@@ -4046,6 +4105,7 @@ var typeToEffectSchemaClass = createRefactor({
4046
4105
  description: "Refactor to Schema.Class",
4047
4106
  apply: fn("typeToEffectSchemaClass.apply")(function* (sourceFile, textRange) {
4048
4107
  const ts = yield* service(TypeScriptApi);
4108
+ const typeChecker = yield* service(TypeCheckerApi);
4049
4109
  const maybeNode = yield* findNodeToProcess(sourceFile, textRange);
4050
4110
  if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
4051
4111
  const node = maybeNode.value;
@@ -4054,6 +4114,7 @@ var typeToEffectSchemaClass = createRefactor({
4054
4114
  description: "Refactor to Schema.Class",
4055
4115
  apply: pipe(
4056
4116
  applyAtNode(sourceFile, node, true),
4117
+ provideService(TypeCheckerApi, typeChecker),
4057
4118
  provideService(TypeScriptApi, ts)
4058
4119
  )
4059
4120
  };