@effect/language-service 0.28.0 → 0.28.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.
- package/README.md +1 -0
- package/cli.js +43 -1
- package/cli.js.map +1 -1
- package/index.js +312 -2
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +43 -1
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -2859,6 +2859,47 @@ function make3(ts, typeChecker) {
|
|
|
2859
2859
|
"TypeParser.scopeType",
|
|
2860
2860
|
(type) => type
|
|
2861
2861
|
);
|
|
2862
|
+
const promiseLike = cachedBy(
|
|
2863
|
+
function(type, atLocation) {
|
|
2864
|
+
const thenProperty = type.getProperty("then");
|
|
2865
|
+
if (!thenProperty) return typeParserIssue("not a promise - missing then property", type, atLocation);
|
|
2866
|
+
const thenType = typeChecker.getTypeOfSymbolAtLocation(thenProperty, atLocation);
|
|
2867
|
+
if (!thenType) return typeParserIssue("not a promise - missing then property", type, atLocation);
|
|
2868
|
+
for (const callSignature of thenType.getCallSignatures()) {
|
|
2869
|
+
const parameter = callSignature.parameters[0];
|
|
2870
|
+
if (!parameter) continue;
|
|
2871
|
+
const parameterType = callSignature.getTypeParameterAtPosition(0);
|
|
2872
|
+
if (!parameterType) continue;
|
|
2873
|
+
let callbackCallSignatures = [];
|
|
2874
|
+
let toTest = [parameterType];
|
|
2875
|
+
while (toTest.length > 0) {
|
|
2876
|
+
const type2 = toTest.shift();
|
|
2877
|
+
if (!type2) continue;
|
|
2878
|
+
const callSignatures = type2.getCallSignatures();
|
|
2879
|
+
callbackCallSignatures = callbackCallSignatures.concat(callSignatures);
|
|
2880
|
+
if (type2.isUnion()) {
|
|
2881
|
+
toTest = toTest.concat(type2.types);
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
for (const callableType of callbackCallSignatures) {
|
|
2885
|
+
const callbackParameter = callableType.parameters[0];
|
|
2886
|
+
if (!callbackParameter) {
|
|
2887
|
+
continue;
|
|
2888
|
+
}
|
|
2889
|
+
const callbackParameterType = callableType.getTypeParameterAtPosition(0);
|
|
2890
|
+
if (!callbackParameterType) {
|
|
2891
|
+
continue;
|
|
2892
|
+
}
|
|
2893
|
+
return succeed({
|
|
2894
|
+
type: callbackParameterType
|
|
2895
|
+
});
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
return typeParserIssue("not a promise", type, atLocation);
|
|
2899
|
+
},
|
|
2900
|
+
"TypeParser.promiseLike",
|
|
2901
|
+
(type) => type
|
|
2902
|
+
);
|
|
2862
2903
|
return {
|
|
2863
2904
|
effectType,
|
|
2864
2905
|
strictEffectType,
|
|
@@ -2874,7 +2915,8 @@ function make3(ts, typeChecker) {
|
|
|
2874
2915
|
contextTag,
|
|
2875
2916
|
pipeableType,
|
|
2876
2917
|
pipeCall,
|
|
2877
|
-
scopeType
|
|
2918
|
+
scopeType,
|
|
2919
|
+
promiseLike
|
|
2878
2920
|
};
|
|
2879
2921
|
}
|
|
2880
2922
|
|
|
@@ -11083,6 +11125,273 @@ var wrapWithPipe = createRefactor({
|
|
|
11083
11125
|
})
|
|
11084
11126
|
});
|
|
11085
11127
|
|
|
11128
|
+
// src/refactors/writeTagClassAccessors.ts
|
|
11129
|
+
var writeTagClassAccessors = createRefactor({
|
|
11130
|
+
name: "writeTagClassAccessors",
|
|
11131
|
+
description: "Implement Service accessors",
|
|
11132
|
+
apply: fn("writeTagClassAccessors.apply")(function* (sourceFile, textRange) {
|
|
11133
|
+
const ts = yield* service(TypeScriptApi);
|
|
11134
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
11135
|
+
const typeParser = yield* service(TypeParser);
|
|
11136
|
+
const effectIdentifier = pipe(
|
|
11137
|
+
yield* option(
|
|
11138
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect")
|
|
11139
|
+
),
|
|
11140
|
+
match({
|
|
11141
|
+
onNone: () => "Effect",
|
|
11142
|
+
onSome: (_) => _.text
|
|
11143
|
+
})
|
|
11144
|
+
);
|
|
11145
|
+
const createConstantProperty = (className, propertyName, type) => ts.factory.createPropertyDeclaration(
|
|
11146
|
+
[ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)],
|
|
11147
|
+
propertyName,
|
|
11148
|
+
void 0,
|
|
11149
|
+
type,
|
|
11150
|
+
ts.factory.createCallExpression(
|
|
11151
|
+
ts.factory.createPropertyAccessExpression(
|
|
11152
|
+
ts.factory.createIdentifier(effectIdentifier),
|
|
11153
|
+
"andThen"
|
|
11154
|
+
),
|
|
11155
|
+
void 0,
|
|
11156
|
+
[
|
|
11157
|
+
ts.factory.createIdentifier(className.text),
|
|
11158
|
+
ts.factory.createArrowFunction(
|
|
11159
|
+
void 0,
|
|
11160
|
+
void 0,
|
|
11161
|
+
[ts.factory.createParameterDeclaration(
|
|
11162
|
+
void 0,
|
|
11163
|
+
void 0,
|
|
11164
|
+
"_"
|
|
11165
|
+
)],
|
|
11166
|
+
void 0,
|
|
11167
|
+
void 0,
|
|
11168
|
+
ts.factory.createPropertyAccessExpression(
|
|
11169
|
+
ts.factory.createIdentifier("_"),
|
|
11170
|
+
propertyName
|
|
11171
|
+
)
|
|
11172
|
+
)
|
|
11173
|
+
]
|
|
11174
|
+
)
|
|
11175
|
+
);
|
|
11176
|
+
const createFunctionProperty = (className, propertyName, type, forceAny) => {
|
|
11177
|
+
const arrowBody = ts.factory.createCallExpression(
|
|
11178
|
+
ts.factory.createPropertyAccessExpression(
|
|
11179
|
+
ts.factory.createIdentifier(effectIdentifier),
|
|
11180
|
+
"andThen"
|
|
11181
|
+
),
|
|
11182
|
+
void 0,
|
|
11183
|
+
[
|
|
11184
|
+
ts.factory.createIdentifier(className.text),
|
|
11185
|
+
ts.factory.createArrowFunction(
|
|
11186
|
+
void 0,
|
|
11187
|
+
void 0,
|
|
11188
|
+
[ts.factory.createParameterDeclaration(
|
|
11189
|
+
void 0,
|
|
11190
|
+
void 0,
|
|
11191
|
+
"_",
|
|
11192
|
+
void 0,
|
|
11193
|
+
forceAny ? ts.factory.createTypeReferenceNode("any") : void 0
|
|
11194
|
+
)],
|
|
11195
|
+
void 0,
|
|
11196
|
+
void 0,
|
|
11197
|
+
ts.factory.createCallExpression(
|
|
11198
|
+
ts.factory.createPropertyAccessExpression(
|
|
11199
|
+
ts.factory.createIdentifier("_"),
|
|
11200
|
+
propertyName
|
|
11201
|
+
),
|
|
11202
|
+
void 0,
|
|
11203
|
+
[
|
|
11204
|
+
ts.factory.createSpreadElement(ts.factory.createIdentifier("args"))
|
|
11205
|
+
]
|
|
11206
|
+
)
|
|
11207
|
+
)
|
|
11208
|
+
]
|
|
11209
|
+
);
|
|
11210
|
+
return ts.factory.createPropertyDeclaration(
|
|
11211
|
+
[ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)],
|
|
11212
|
+
propertyName,
|
|
11213
|
+
void 0,
|
|
11214
|
+
type,
|
|
11215
|
+
ts.factory.createArrowFunction(
|
|
11216
|
+
void 0,
|
|
11217
|
+
void 0,
|
|
11218
|
+
[ts.factory.createParameterDeclaration(
|
|
11219
|
+
void 0,
|
|
11220
|
+
ts.factory.createToken(ts.SyntaxKind.DotDotDotToken),
|
|
11221
|
+
"args",
|
|
11222
|
+
void 0,
|
|
11223
|
+
forceAny ? ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("any")) : void 0
|
|
11224
|
+
)],
|
|
11225
|
+
void 0,
|
|
11226
|
+
void 0,
|
|
11227
|
+
forceAny ? ts.factory.createAsExpression(arrowBody, ts.factory.createTypeReferenceNode("any")) : arrowBody
|
|
11228
|
+
)
|
|
11229
|
+
);
|
|
11230
|
+
};
|
|
11231
|
+
const generateReturnType = (type, atLocation, className) => pipe(
|
|
11232
|
+
typeParser.effectType(type, atLocation),
|
|
11233
|
+
flatMap2((returnedEffect) => {
|
|
11234
|
+
const contextType = returnedEffect.R.flags & ts.TypeFlags.Never ? ts.factory.createTypeReferenceNode(className.text) : ts.factory.createUnionTypeNode(
|
|
11235
|
+
[
|
|
11236
|
+
ts.factory.createTypeReferenceNode(className.text),
|
|
11237
|
+
typeChecker.typeToTypeNode(returnedEffect.R, atLocation, ts.NodeBuilderFlags.NoTruncation)
|
|
11238
|
+
]
|
|
11239
|
+
);
|
|
11240
|
+
const successType = typeChecker.typeToTypeNode(
|
|
11241
|
+
returnedEffect.A,
|
|
11242
|
+
atLocation,
|
|
11243
|
+
ts.NodeBuilderFlags.NoTruncation
|
|
11244
|
+
);
|
|
11245
|
+
if (!successType) return fail("error generating success type");
|
|
11246
|
+
const failureType = typeChecker.typeToTypeNode(
|
|
11247
|
+
returnedEffect.E,
|
|
11248
|
+
atLocation,
|
|
11249
|
+
ts.NodeBuilderFlags.NoTruncation
|
|
11250
|
+
);
|
|
11251
|
+
if (!failureType) return fail("error generating failure type");
|
|
11252
|
+
const typeNode = ts.factory.createTypeReferenceNode(
|
|
11253
|
+
ts.factory.createQualifiedName(
|
|
11254
|
+
ts.factory.createIdentifier(effectIdentifier),
|
|
11255
|
+
ts.factory.createIdentifier("Effect")
|
|
11256
|
+
),
|
|
11257
|
+
[successType, failureType, contextType]
|
|
11258
|
+
);
|
|
11259
|
+
return succeed(typeNode);
|
|
11260
|
+
}),
|
|
11261
|
+
orElse2(
|
|
11262
|
+
() => pipe(
|
|
11263
|
+
typeParser.promiseLike(type, atLocation),
|
|
11264
|
+
flatMap2(({ type: type2 }) => {
|
|
11265
|
+
const successType = typeChecker.typeToTypeNode(
|
|
11266
|
+
type2,
|
|
11267
|
+
atLocation,
|
|
11268
|
+
ts.NodeBuilderFlags.NoTruncation
|
|
11269
|
+
);
|
|
11270
|
+
if (!successType) return fail("error generating success type");
|
|
11271
|
+
return succeed(ts.factory.createTypeReferenceNode(
|
|
11272
|
+
ts.factory.createQualifiedName(
|
|
11273
|
+
ts.factory.createIdentifier(effectIdentifier),
|
|
11274
|
+
ts.factory.createIdentifier("Effect")
|
|
11275
|
+
),
|
|
11276
|
+
[
|
|
11277
|
+
successType,
|
|
11278
|
+
ts.factory.createTypeReferenceNode(
|
|
11279
|
+
ts.factory.createQualifiedName(
|
|
11280
|
+
ts.factory.createIdentifier("Cause"),
|
|
11281
|
+
ts.factory.createIdentifier("UnknownException")
|
|
11282
|
+
)
|
|
11283
|
+
),
|
|
11284
|
+
ts.factory.createTypeReferenceNode(className.text)
|
|
11285
|
+
]
|
|
11286
|
+
));
|
|
11287
|
+
})
|
|
11288
|
+
)
|
|
11289
|
+
),
|
|
11290
|
+
orElse2(() => {
|
|
11291
|
+
const successType = typeChecker.typeToTypeNode(type, atLocation, ts.NodeBuilderFlags.NoTruncation);
|
|
11292
|
+
if (!successType) return fail("error generating success type");
|
|
11293
|
+
const typeNode = ts.factory.createTypeReferenceNode(
|
|
11294
|
+
ts.factory.createQualifiedName(
|
|
11295
|
+
ts.factory.createIdentifier(effectIdentifier),
|
|
11296
|
+
ts.factory.createIdentifier("Effect")
|
|
11297
|
+
),
|
|
11298
|
+
[
|
|
11299
|
+
successType,
|
|
11300
|
+
ts.factory.createTypeReferenceNode("never"),
|
|
11301
|
+
ts.factory.createTypeReferenceNode(className.text)
|
|
11302
|
+
]
|
|
11303
|
+
);
|
|
11304
|
+
return succeed(typeNode);
|
|
11305
|
+
})
|
|
11306
|
+
);
|
|
11307
|
+
const proxySignature = (signature, atLocation, className) => gen(function* () {
|
|
11308
|
+
const signatureDeclaration = typeChecker.signatureToSignatureDeclaration(
|
|
11309
|
+
signature,
|
|
11310
|
+
ts.SyntaxKind.FunctionType,
|
|
11311
|
+
atLocation,
|
|
11312
|
+
ts.NodeBuilderFlags.NoTruncation
|
|
11313
|
+
);
|
|
11314
|
+
if (!signatureDeclaration) return yield* fail("error generating signature");
|
|
11315
|
+
const returnType = yield* generateReturnType(signature.getReturnType(), atLocation, className);
|
|
11316
|
+
return ts.factory.createFunctionTypeNode(
|
|
11317
|
+
signatureDeclaration.typeParameters,
|
|
11318
|
+
signatureDeclaration.parameters,
|
|
11319
|
+
returnType
|
|
11320
|
+
);
|
|
11321
|
+
});
|
|
11322
|
+
const writeAccessors = fn("writeTagClassAccessors.writeAccessors")(
|
|
11323
|
+
function* (service2, className, atLocation) {
|
|
11324
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
11325
|
+
const insertLocation = atLocation.members.length > 0 ? atLocation.members[0].pos : atLocation.getEnd() - 1;
|
|
11326
|
+
for (const property of typeChecker.getPropertiesOfType(service2)) {
|
|
11327
|
+
const servicePropertyType = typeChecker.getTypeOfSymbolAtLocation(property, atLocation);
|
|
11328
|
+
const callSignatures = [];
|
|
11329
|
+
let propertyDeclaration = void 0;
|
|
11330
|
+
for (const signature of servicePropertyType.getCallSignatures()) {
|
|
11331
|
+
yield* pipe(
|
|
11332
|
+
proxySignature(signature, atLocation, className),
|
|
11333
|
+
map4((sig) => {
|
|
11334
|
+
callSignatures.push(sig);
|
|
11335
|
+
}),
|
|
11336
|
+
ignore
|
|
11337
|
+
);
|
|
11338
|
+
}
|
|
11339
|
+
if (callSignatures.length === 0) {
|
|
11340
|
+
yield* pipe(
|
|
11341
|
+
generateReturnType(servicePropertyType, atLocation, className),
|
|
11342
|
+
map4((type) => {
|
|
11343
|
+
propertyDeclaration = createConstantProperty(className, property.getName(), type);
|
|
11344
|
+
}),
|
|
11345
|
+
ignore
|
|
11346
|
+
);
|
|
11347
|
+
} else {
|
|
11348
|
+
const allSignatures = ts.factory.createIntersectionTypeNode(callSignatures);
|
|
11349
|
+
const type = yield* simplifyTypeNode(allSignatures);
|
|
11350
|
+
propertyDeclaration = createFunctionProperty(className, property.getName(), type, callSignatures.length > 1);
|
|
11351
|
+
}
|
|
11352
|
+
if (propertyDeclaration) {
|
|
11353
|
+
const oldProperty = atLocation.members.filter(ts.isPropertyDeclaration).find((p) => {
|
|
11354
|
+
const symbol3 = typeChecker.getSymbolAtLocation(p.name);
|
|
11355
|
+
return symbol3?.getName() === property.getName();
|
|
11356
|
+
});
|
|
11357
|
+
if (oldProperty) {
|
|
11358
|
+
changeTracker.deleteRange(sourceFile, {
|
|
11359
|
+
pos: oldProperty.getStart(sourceFile),
|
|
11360
|
+
end: oldProperty.getEnd()
|
|
11361
|
+
});
|
|
11362
|
+
changeTracker.insertNodeAt(sourceFile, oldProperty.getStart(sourceFile), propertyDeclaration);
|
|
11363
|
+
} else {
|
|
11364
|
+
changeTracker.insertNodeAt(sourceFile, insertLocation, propertyDeclaration, { suffix: "\n" });
|
|
11365
|
+
}
|
|
11366
|
+
}
|
|
11367
|
+
}
|
|
11368
|
+
}
|
|
11369
|
+
);
|
|
11370
|
+
const writeTagClassAccessors2 = (node) => gen(function* () {
|
|
11371
|
+
if (!ts.isClassDeclaration(node)) return yield* fail(new RefactorNotApplicableError());
|
|
11372
|
+
if (!node.name) return yield* fail(new RefactorNotApplicableError());
|
|
11373
|
+
const classSym = typeChecker.getSymbolAtLocation(node.name);
|
|
11374
|
+
if (!classSym) return yield* fail(new RefactorNotApplicableError());
|
|
11375
|
+
const type = typeChecker.getTypeOfSymbol(classSym);
|
|
11376
|
+
const { Service } = yield* pipe(
|
|
11377
|
+
typeParser.contextTag(type, node),
|
|
11378
|
+
orElse2(() => fail(new RefactorNotApplicableError()))
|
|
11379
|
+
);
|
|
11380
|
+
return {
|
|
11381
|
+
kind: "refactor.rewrite.effect.writeTagClassAccessors",
|
|
11382
|
+
description: "Implement Service accessors",
|
|
11383
|
+
apply: pipe(
|
|
11384
|
+
writeAccessors(Service, node.name, node),
|
|
11385
|
+
provideService(TypeCheckerApi, typeChecker),
|
|
11386
|
+
provideService(TypeScriptApi, ts)
|
|
11387
|
+
)
|
|
11388
|
+
};
|
|
11389
|
+
});
|
|
11390
|
+
const parentNodes = yield* getAncestorNodesInRange(sourceFile, textRange);
|
|
11391
|
+
return yield* firstSuccessOf(parentNodes.map(writeTagClassAccessors2));
|
|
11392
|
+
})
|
|
11393
|
+
});
|
|
11394
|
+
|
|
11086
11395
|
// src/refactors.ts
|
|
11087
11396
|
var refactors = [
|
|
11088
11397
|
asyncAwaitToGen,
|
|
@@ -11100,7 +11409,8 @@ var refactors = [
|
|
|
11100
11409
|
wrapWithEffectGen,
|
|
11101
11410
|
wrapWithPipe,
|
|
11102
11411
|
effectGenToFn,
|
|
11103
|
-
togglePipeStyle
|
|
11412
|
+
togglePipeStyle,
|
|
11413
|
+
writeTagClassAccessors
|
|
11104
11414
|
];
|
|
11105
11415
|
|
|
11106
11416
|
// src/index.ts
|