@effect/language-service 0.18.0 → 0.19.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 +2 -0
- package/index.js +562 -51
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +517 -29
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -922,6 +922,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => isNone2(self) ? none2() : some2(
|
|
|
922
922
|
// node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Array.js
|
|
923
923
|
var fromIterable = (collection) => Array.isArray(collection) ? collection : Array.from(collection);
|
|
924
924
|
var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
|
|
925
|
+
var appendAll = /* @__PURE__ */ dual(2, (self, that) => fromIterable(self).concat(fromIterable(that)));
|
|
925
926
|
var isArray = Array.isArray;
|
|
926
927
|
var isEmptyArray = (self) => self.length === 0;
|
|
927
928
|
var isEmptyReadonlyArray = isEmptyArray;
|
|
@@ -2094,6 +2095,51 @@ var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (so
|
|
|
2094
2095
|
cache.expectedAndRealType.set(sourceFile, result);
|
|
2095
2096
|
return result;
|
|
2096
2097
|
});
|
|
2098
|
+
var appendToUniqueTypesMap = fn(
|
|
2099
|
+
"TypeCheckerApi.appendToUniqueTypesMap"
|
|
2100
|
+
)(
|
|
2101
|
+
function* (memory, initialType, excludeNever) {
|
|
2102
|
+
const ts = yield* service(TypeScriptApi);
|
|
2103
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2104
|
+
const newIndexes = /* @__PURE__ */ new Set();
|
|
2105
|
+
const knownIndexes = /* @__PURE__ */ new Set();
|
|
2106
|
+
let toTest = [initialType];
|
|
2107
|
+
while (toTest.length > 0) {
|
|
2108
|
+
const type = toTest.pop();
|
|
2109
|
+
if (!type) break;
|
|
2110
|
+
if (excludeNever && type.flags & ts.TypeFlags.Never) {
|
|
2111
|
+
continue;
|
|
2112
|
+
}
|
|
2113
|
+
if (type.isUnion()) {
|
|
2114
|
+
toTest = toTest.concat(type.types);
|
|
2115
|
+
} else {
|
|
2116
|
+
const foundMatch = [];
|
|
2117
|
+
for (const [typeId, knownType] of memory.entries()) {
|
|
2118
|
+
const areSame = typeChecker.isTypeAssignableTo(knownType, type) && typeChecker.isTypeAssignableTo(type, knownType);
|
|
2119
|
+
if (areSame) {
|
|
2120
|
+
foundMatch.push(typeId);
|
|
2121
|
+
break;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
if (foundMatch.length === 0) {
|
|
2125
|
+
const newId = "t" + (memory.size + 1);
|
|
2126
|
+
memory.set(newId, type);
|
|
2127
|
+
newIndexes.add(newId);
|
|
2128
|
+
} else {
|
|
2129
|
+
knownIndexes.add(foundMatch[0]);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
return {
|
|
2134
|
+
newIndexes,
|
|
2135
|
+
knownIndexes,
|
|
2136
|
+
allIndexes: pipe(
|
|
2137
|
+
fromIterable(newIndexes),
|
|
2138
|
+
appendAll(fromIterable(knownIndexes))
|
|
2139
|
+
)
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
);
|
|
2097
2143
|
|
|
2098
2144
|
// src/utils/TypeParser.ts
|
|
2099
2145
|
var TypeParserIssue = class {
|
|
@@ -2114,6 +2160,13 @@ function covariantTypeArgument(type) {
|
|
|
2114
2160
|
}
|
|
2115
2161
|
return succeed(signatures[0].getReturnType());
|
|
2116
2162
|
}
|
|
2163
|
+
function contravariantTypeArgument(type) {
|
|
2164
|
+
const signatures = type.getCallSignatures();
|
|
2165
|
+
if (signatures.length !== 1) {
|
|
2166
|
+
return typeParserIssue("Contravariant type has no call signature", type);
|
|
2167
|
+
}
|
|
2168
|
+
return succeed(signatures[0].getTypeParameterAtPosition(0));
|
|
2169
|
+
}
|
|
2117
2170
|
function invariantTypeArgument(type) {
|
|
2118
2171
|
const signatures = type.getCallSignatures();
|
|
2119
2172
|
if (signatures.length !== 1) {
|
|
@@ -2145,6 +2198,19 @@ var varianceStructCovariantType = fn("TypeParser.varianceStructCovariantType")(
|
|
|
2145
2198
|
return yield* covariantTypeArgument(propertyType);
|
|
2146
2199
|
}
|
|
2147
2200
|
);
|
|
2201
|
+
var varianceStructContravariantType = fn(
|
|
2202
|
+
"TypeParser.varianceStructContravariantType"
|
|
2203
|
+
)(
|
|
2204
|
+
function* (type, atLocation, propertyName) {
|
|
2205
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2206
|
+
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
2207
|
+
if (!propertySymbol) {
|
|
2208
|
+
return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
2209
|
+
}
|
|
2210
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2211
|
+
return yield* contravariantTypeArgument(propertyType);
|
|
2212
|
+
}
|
|
2213
|
+
);
|
|
2148
2214
|
var varianceStructInvariantType = fn("TypeParser.varianceStructInvariantType")(
|
|
2149
2215
|
function* (type, atLocation, propertyName) {
|
|
2150
2216
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -2163,6 +2229,13 @@ var effectVarianceStruct = fn("TypeParser.effectVarianceStruct")(function* (type
|
|
|
2163
2229
|
R: yield* varianceStructCovariantType(type, atLocation, "_R")
|
|
2164
2230
|
};
|
|
2165
2231
|
});
|
|
2232
|
+
var layerVarianceStruct = fn("TypeParser.layerVarianceStruct")(function* (type, atLocation) {
|
|
2233
|
+
return {
|
|
2234
|
+
ROut: yield* varianceStructContravariantType(type, atLocation, "_ROut"),
|
|
2235
|
+
E: yield* varianceStructCovariantType(type, atLocation, "_E"),
|
|
2236
|
+
RIn: yield* varianceStructCovariantType(type, atLocation, "_RIn")
|
|
2237
|
+
};
|
|
2238
|
+
});
|
|
2166
2239
|
var effectType = fn("TypeParser.effectType")(function* (type, atLocation) {
|
|
2167
2240
|
const ts = yield* service(TypeScriptApi);
|
|
2168
2241
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -2183,6 +2256,26 @@ var effectType = fn("TypeParser.effectType")(function* (type, atLocation) {
|
|
|
2183
2256
|
}
|
|
2184
2257
|
return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
|
|
2185
2258
|
});
|
|
2259
|
+
var layerType = fn("TypeParser.layerType")(function* (type, atLocation) {
|
|
2260
|
+
const ts = yield* service(TypeScriptApi);
|
|
2261
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2262
|
+
yield* pipeableType(type, atLocation);
|
|
2263
|
+
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2264
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2265
|
+
);
|
|
2266
|
+
propertiesSymbols.sort((a, b) => b.name.indexOf("LayerTypeId") - a.name.indexOf("LayerTypeId"));
|
|
2267
|
+
for (const propertySymbol of propertiesSymbols) {
|
|
2268
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2269
|
+
const varianceArgs = yield* option(layerVarianceStruct(
|
|
2270
|
+
propertyType,
|
|
2271
|
+
atLocation
|
|
2272
|
+
));
|
|
2273
|
+
if (isSome2(varianceArgs)) {
|
|
2274
|
+
return varianceArgs.value;
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
return yield* typeParserIssue("Type has no layer variance struct", type, atLocation);
|
|
2278
|
+
});
|
|
2186
2279
|
var fiberType = fn("TypeParser.fiberType")(function* (type, atLocation) {
|
|
2187
2280
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2188
2281
|
const awaitSymbol = typeChecker.getPropertyOfType(type, "await");
|
|
@@ -2348,19 +2441,68 @@ var effectFnGen = fn("TypeParser.effectFnGen")(function* (node) {
|
|
|
2348
2441
|
functionStar: generatorFunction.getFirstToken()
|
|
2349
2442
|
};
|
|
2350
2443
|
});
|
|
2351
|
-
var
|
|
2444
|
+
var unnecessaryEffectGen = fn("TypeParser.unnecessaryEffectGen")(function* (node) {
|
|
2352
2445
|
const ts = yield* service(TypeScriptApi);
|
|
2353
2446
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2447
|
+
const { body } = yield* effectGen(node);
|
|
2448
|
+
if (body.statements.length !== 1) {
|
|
2449
|
+
return yield* typeParserIssue(
|
|
2450
|
+
"Generator body should have a single statement",
|
|
2451
|
+
void 0,
|
|
2452
|
+
node
|
|
2453
|
+
);
|
|
2454
|
+
}
|
|
2455
|
+
let explicitReturn = false;
|
|
2456
|
+
let nodeToCheck = body.statements[0];
|
|
2457
|
+
while (nodeToCheck) {
|
|
2458
|
+
if (ts.isReturnStatement(nodeToCheck) && nodeToCheck.expression) {
|
|
2459
|
+
nodeToCheck = nodeToCheck.expression;
|
|
2460
|
+
explicitReturn = true;
|
|
2461
|
+
continue;
|
|
2462
|
+
}
|
|
2463
|
+
if (ts.isExpressionStatement(nodeToCheck)) {
|
|
2464
|
+
nodeToCheck = nodeToCheck.expression;
|
|
2465
|
+
continue;
|
|
2466
|
+
}
|
|
2467
|
+
if (ts.isYieldExpression(nodeToCheck) && nodeToCheck.asteriskToken && nodeToCheck.expression) {
|
|
2468
|
+
const yieldedExpression = nodeToCheck.expression;
|
|
2469
|
+
const type = typeChecker.getTypeAtLocation(yieldedExpression);
|
|
2470
|
+
const { A: successType } = yield* effectType(type, yieldedExpression);
|
|
2471
|
+
let replacementNode = succeed(yieldedExpression);
|
|
2472
|
+
if (!explicitReturn && !(successType.flags & ts.TypeFlags.VoidLike)) {
|
|
2473
|
+
replacementNode = pipe(
|
|
2474
|
+
gen2(function* () {
|
|
2475
|
+
const effectIdentifier = pipe(
|
|
2476
|
+
yield* option(
|
|
2477
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(node.getSourceFile(), "effect", "Effect")
|
|
2478
|
+
),
|
|
2479
|
+
match2({
|
|
2480
|
+
onNone: () => "Effect",
|
|
2481
|
+
onSome: (_) => _.text
|
|
2482
|
+
})
|
|
2483
|
+
);
|
|
2484
|
+
return ts.factory.createCallExpression(
|
|
2485
|
+
ts.factory.createPropertyAccessExpression(
|
|
2486
|
+
ts.factory.createIdentifier(effectIdentifier),
|
|
2487
|
+
"asVoid"
|
|
2488
|
+
),
|
|
2489
|
+
void 0,
|
|
2490
|
+
[
|
|
2491
|
+
yieldedExpression
|
|
2492
|
+
]
|
|
2493
|
+
);
|
|
2494
|
+
}),
|
|
2495
|
+
provideService(TypeScriptApi, ts)
|
|
2496
|
+
);
|
|
2497
|
+
}
|
|
2498
|
+
return { node, body, yieldedExpression, replacementNode };
|
|
2499
|
+
}
|
|
2500
|
+
break;
|
|
2359
2501
|
}
|
|
2360
2502
|
return yield* typeParserIssue(
|
|
2361
|
-
"
|
|
2503
|
+
"Not an handled node",
|
|
2362
2504
|
void 0,
|
|
2363
|
-
|
|
2505
|
+
node
|
|
2364
2506
|
);
|
|
2365
2507
|
});
|
|
2366
2508
|
var effectSchemaVarianceStruct = fn("TypeParser.effectSchemaVarianceStruct")(
|
|
@@ -2792,7 +2934,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
2792
2934
|
});
|
|
2793
2935
|
|
|
2794
2936
|
// src/diagnostics/unnecessaryEffectGen.ts
|
|
2795
|
-
var
|
|
2937
|
+
var unnecessaryEffectGen2 = createDiagnostic({
|
|
2796
2938
|
name: "unnecessaryEffectGen",
|
|
2797
2939
|
code: 5,
|
|
2798
2940
|
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile) {
|
|
@@ -2808,13 +2950,9 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
2808
2950
|
while (nodeToVisit.length > 0) {
|
|
2809
2951
|
const node = nodeToVisit.shift();
|
|
2810
2952
|
ts.forEachChild(node, appendNodeToVisit);
|
|
2811
|
-
const maybeNode = yield*
|
|
2812
|
-
effectGen(node),
|
|
2813
|
-
flatMap3(({ body }) => returnYieldEffectBlock(body)),
|
|
2814
|
-
option
|
|
2815
|
-
);
|
|
2953
|
+
const maybeNode = yield* option(unnecessaryEffectGen(node));
|
|
2816
2954
|
if (isSome2(maybeNode)) {
|
|
2817
|
-
unnecessaryGenerators.set(node, maybeNode.value);
|
|
2955
|
+
unnecessaryGenerators.set(node, maybeNode.value.replacementNode);
|
|
2818
2956
|
}
|
|
2819
2957
|
}
|
|
2820
2958
|
unnecessaryGenerators.forEach(
|
|
@@ -2829,7 +2967,7 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
2829
2967
|
const textChanges = yield* service(
|
|
2830
2968
|
ChangeTracker
|
|
2831
2969
|
);
|
|
2832
|
-
textChanges.replaceNode(sourceFile, effectGenCall, yieldedResult);
|
|
2970
|
+
textChanges.replaceNode(sourceFile, effectGenCall, yield* yieldedResult);
|
|
2833
2971
|
})
|
|
2834
2972
|
}]
|
|
2835
2973
|
})
|
|
@@ -2845,24 +2983,26 @@ var diagnostics = [
|
|
|
2845
2983
|
missingEffectError,
|
|
2846
2984
|
floatingEffect,
|
|
2847
2985
|
missingStarInYieldEffectGen,
|
|
2848
|
-
|
|
2986
|
+
unnecessaryEffectGen2
|
|
2849
2987
|
];
|
|
2850
2988
|
|
|
2851
|
-
// src/quickinfo.ts
|
|
2989
|
+
// src/quickinfo/dedupeJsDocs.ts
|
|
2852
2990
|
var SymbolDisplayPartEq = make((fa, fb) => fa.kind === fb.kind && fa.text === fb.text);
|
|
2853
2991
|
var JSDocTagInfoEq = make(
|
|
2854
2992
|
(fa, fb) => fa.name === fb.name && typeof fa.text === typeof fb.text && (typeof fa.text !== "undefined" ? array(SymbolDisplayPartEq)(fa.text, fb.text) : true)
|
|
2855
2993
|
);
|
|
2856
|
-
function
|
|
2857
|
-
if (!
|
|
2858
|
-
if (
|
|
2859
|
-
return {
|
|
2860
|
-
...
|
|
2861
|
-
tags: dedupeWith(
|
|
2862
|
-
};
|
|
2994
|
+
function dedupeJsDocs(quickInfo2) {
|
|
2995
|
+
if (!quickInfo2) return succeed(quickInfo2);
|
|
2996
|
+
if (quickInfo2.tags) {
|
|
2997
|
+
return succeed({
|
|
2998
|
+
...quickInfo2,
|
|
2999
|
+
tags: dedupeWith(quickInfo2.tags, JSDocTagInfoEq)
|
|
3000
|
+
});
|
|
2863
3001
|
}
|
|
2864
|
-
return
|
|
3002
|
+
return succeed(quickInfo2);
|
|
2865
3003
|
}
|
|
3004
|
+
|
|
3005
|
+
// src/quickinfo/effectTypeArgs.ts
|
|
2866
3006
|
function formatTypeForQuickInfo(channelType, channelName) {
|
|
2867
3007
|
return gen2(function* () {
|
|
2868
3008
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -2875,7 +3015,7 @@ function formatTypeForQuickInfo(channelType, channelName) {
|
|
|
2875
3015
|
return `type ${channelName} = ${stringRepresentation}`;
|
|
2876
3016
|
});
|
|
2877
3017
|
}
|
|
2878
|
-
function
|
|
3018
|
+
function effectTypeArgs(sourceFile, position, quickInfo2) {
|
|
2879
3019
|
return pipe(
|
|
2880
3020
|
gen2(function* () {
|
|
2881
3021
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -2884,11 +3024,11 @@ function prependEffectTypeArguments(sourceFile, position, quickInfo) {
|
|
|
2884
3024
|
yield* getAncestorNodesInRange(sourceFile, toTextRange(position)),
|
|
2885
3025
|
head
|
|
2886
3026
|
);
|
|
2887
|
-
if (isNone2(maybeNode)) return
|
|
3027
|
+
if (isNone2(maybeNode)) return quickInfo2;
|
|
2888
3028
|
const node = maybeNode.value;
|
|
2889
|
-
const hasTruncationHappened =
|
|
2890
|
-
const nodeForType = !
|
|
2891
|
-
if (!nodeForType) return
|
|
3029
|
+
const hasTruncationHappened = quickInfo2 && ts.displayPartsToString(quickInfo2.displayParts).indexOf("...") > -1;
|
|
3030
|
+
const nodeForType = !quickInfo2 && ts.isYieldExpression(node) && node.asteriskToken && node.expression ? node.expression : hasTruncationHappened ? node : void 0;
|
|
3031
|
+
if (!nodeForType) return quickInfo2;
|
|
2892
3032
|
const effectType2 = yield* effectType(
|
|
2893
3033
|
typeChecker.getTypeAtLocation(nodeForType),
|
|
2894
3034
|
nodeForType
|
|
@@ -2897,7 +3037,7 @@ function prependEffectTypeArguments(sourceFile, position, quickInfo) {
|
|
|
2897
3037
|
kind: "text",
|
|
2898
3038
|
text: "```ts\n/* Effect Type Parameters */\n" + (yield* formatTypeForQuickInfo(effectType2.A, "Success")) + "\n" + (yield* formatTypeForQuickInfo(effectType2.E, "Failure")) + "\n" + (yield* formatTypeForQuickInfo(effectType2.R, "Requirements")) + "\n```\n"
|
|
2899
3039
|
}];
|
|
2900
|
-
if (!
|
|
3040
|
+
if (!quickInfo2) {
|
|
2901
3041
|
const start = node.getStart();
|
|
2902
3042
|
const end = node.getEnd();
|
|
2903
3043
|
return {
|
|
@@ -2907,21 +3047,398 @@ function prependEffectTypeArguments(sourceFile, position, quickInfo) {
|
|
|
2907
3047
|
documentation: effectTypeArgsDocumentation
|
|
2908
3048
|
};
|
|
2909
3049
|
}
|
|
2910
|
-
if (
|
|
3050
|
+
if (quickInfo2.documentation) {
|
|
2911
3051
|
return {
|
|
2912
|
-
...
|
|
2913
|
-
documentation: effectTypeArgsDocumentation.concat(
|
|
3052
|
+
...quickInfo2,
|
|
3053
|
+
documentation: effectTypeArgsDocumentation.concat(quickInfo2.documentation)
|
|
2914
3054
|
};
|
|
2915
3055
|
}
|
|
2916
3056
|
return {
|
|
2917
|
-
...
|
|
3057
|
+
...quickInfo2,
|
|
2918
3058
|
documentation: effectTypeArgsDocumentation
|
|
2919
3059
|
};
|
|
2920
3060
|
}),
|
|
2921
|
-
orElse3(() => succeed(
|
|
3061
|
+
orElse3(() => succeed(quickInfo2))
|
|
2922
3062
|
);
|
|
2923
3063
|
}
|
|
2924
3064
|
|
|
3065
|
+
// src/quickinfo/layerInfo.ts
|
|
3066
|
+
var UnableToProduceLayerGraphError = class {
|
|
3067
|
+
constructor(message, node) {
|
|
3068
|
+
this.message = message;
|
|
3069
|
+
this.node = node;
|
|
3070
|
+
}
|
|
3071
|
+
_tag = "@effect/language-service/UnableToProduceLayerGraphError";
|
|
3072
|
+
};
|
|
3073
|
+
var GraphNodeLeaf = class {
|
|
3074
|
+
constructor(id, node, rout, rin) {
|
|
3075
|
+
this.id = id;
|
|
3076
|
+
this.node = node;
|
|
3077
|
+
this.rout = rout;
|
|
3078
|
+
this.rin = rin;
|
|
3079
|
+
}
|
|
3080
|
+
_tag = "GraphNodeLeaf";
|
|
3081
|
+
};
|
|
3082
|
+
var GraphNodeCompoundTransform = class {
|
|
3083
|
+
constructor(id, node, args, rout, rin) {
|
|
3084
|
+
this.id = id;
|
|
3085
|
+
this.node = node;
|
|
3086
|
+
this.args = args;
|
|
3087
|
+
this.rout = rout;
|
|
3088
|
+
this.rin = rin;
|
|
3089
|
+
}
|
|
3090
|
+
_tag = "GraphNodeCompoundTransform";
|
|
3091
|
+
};
|
|
3092
|
+
function processLayerGraphNode(ctx, node, pipedInGraphNode) {
|
|
3093
|
+
return gen2(function* () {
|
|
3094
|
+
const ts = yield* service(TypeScriptApi);
|
|
3095
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3096
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "pipe") {
|
|
3097
|
+
let graphNode = yield* processLayerGraphNode(ctx, node.expression.expression, void 0);
|
|
3098
|
+
for (const entry of node.arguments) {
|
|
3099
|
+
graphNode = yield* processLayerGraphNode(ctx, entry, graphNode);
|
|
3100
|
+
}
|
|
3101
|
+
return graphNode;
|
|
3102
|
+
}
|
|
3103
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "pipe" && node.arguments.length > 0) {
|
|
3104
|
+
let graphNode = yield* processLayerGraphNode(ctx, node.arguments[0], void 0);
|
|
3105
|
+
for (let i = 1; i < node.arguments.length; i++) {
|
|
3106
|
+
graphNode = yield* processLayerGraphNode(ctx, node.arguments[i], graphNode);
|
|
3107
|
+
}
|
|
3108
|
+
return graphNode;
|
|
3109
|
+
}
|
|
3110
|
+
if (ts.isCallExpression(node)) {
|
|
3111
|
+
const type = typeChecker.getTypeAtLocation(node);
|
|
3112
|
+
const maybeLayer = yield* option(layerType(type, node));
|
|
3113
|
+
if (isSome2(maybeLayer)) {
|
|
3114
|
+
const argNodes = yield* option(
|
|
3115
|
+
all2(...node.arguments.map((_) => processLayerGraphNode(ctx, _, void 0)))
|
|
3116
|
+
);
|
|
3117
|
+
if (isSome2(argNodes) && argNodes.value.length === node.arguments.length) {
|
|
3118
|
+
const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
|
|
3119
|
+
ctx.services,
|
|
3120
|
+
maybeLayer.value.ROut,
|
|
3121
|
+
true
|
|
3122
|
+
);
|
|
3123
|
+
const { allIndexes: inTypes } = yield* appendToUniqueTypesMap(
|
|
3124
|
+
ctx.services,
|
|
3125
|
+
maybeLayer.value.RIn,
|
|
3126
|
+
true
|
|
3127
|
+
);
|
|
3128
|
+
return new GraphNodeCompoundTransform(
|
|
3129
|
+
ctx.nextId(),
|
|
3130
|
+
node,
|
|
3131
|
+
argNodes.value,
|
|
3132
|
+
outTypes,
|
|
3133
|
+
inTypes
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
if (pipedInGraphNode && ts.isExpression(node)) {
|
|
3139
|
+
const type = typeChecker.getContextualType(node);
|
|
3140
|
+
if (type) {
|
|
3141
|
+
const callSignatures = type.getCallSignatures();
|
|
3142
|
+
if (callSignatures.length === 1) {
|
|
3143
|
+
const [signature] = callSignatures;
|
|
3144
|
+
const returnType = signature.getReturnType();
|
|
3145
|
+
const maybeLayer = yield* option(layerType(returnType, node));
|
|
3146
|
+
if (isSome2(maybeLayer)) {
|
|
3147
|
+
const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
|
|
3148
|
+
ctx.services,
|
|
3149
|
+
maybeLayer.value.ROut,
|
|
3150
|
+
true
|
|
3151
|
+
);
|
|
3152
|
+
const { allIndexes: inTypes } = yield* appendToUniqueTypesMap(
|
|
3153
|
+
ctx.services,
|
|
3154
|
+
maybeLayer.value.RIn,
|
|
3155
|
+
true
|
|
3156
|
+
);
|
|
3157
|
+
if (ts.isCallExpression(node)) {
|
|
3158
|
+
const argNodes = yield* option(
|
|
3159
|
+
all2(...node.arguments.map((_) => processLayerGraphNode(ctx, _, void 0)))
|
|
3160
|
+
);
|
|
3161
|
+
if (isSome2(argNodes) && argNodes.value.length === node.arguments.length) {
|
|
3162
|
+
return new GraphNodeCompoundTransform(
|
|
3163
|
+
ctx.nextId(),
|
|
3164
|
+
node,
|
|
3165
|
+
[pipedInGraphNode, ...argNodes.value],
|
|
3166
|
+
outTypes,
|
|
3167
|
+
inTypes
|
|
3168
|
+
);
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
const argNode = yield* option(processLayerGraphNode(ctx, node, void 0));
|
|
3172
|
+
if (isSome2(argNode)) {
|
|
3173
|
+
return new GraphNodeCompoundTransform(
|
|
3174
|
+
ctx.nextId(),
|
|
3175
|
+
node,
|
|
3176
|
+
[pipedInGraphNode, argNode.value],
|
|
3177
|
+
outTypes,
|
|
3178
|
+
inTypes
|
|
3179
|
+
);
|
|
3180
|
+
} else {
|
|
3181
|
+
return new GraphNodeCompoundTransform(
|
|
3182
|
+
ctx.nextId(),
|
|
3183
|
+
node,
|
|
3184
|
+
[pipedInGraphNode],
|
|
3185
|
+
outTypes,
|
|
3186
|
+
inTypes
|
|
3187
|
+
);
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
if (ts.isExpression(node)) {
|
|
3194
|
+
const type = typeChecker.getTypeAtLocation(node);
|
|
3195
|
+
const maybeLayer = yield* option(layerType(type, node));
|
|
3196
|
+
if (isSome2(maybeLayer)) {
|
|
3197
|
+
const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
|
|
3198
|
+
ctx.services,
|
|
3199
|
+
maybeLayer.value.ROut,
|
|
3200
|
+
true
|
|
3201
|
+
);
|
|
3202
|
+
const { allIndexes: inTypes } = yield* appendToUniqueTypesMap(
|
|
3203
|
+
ctx.services,
|
|
3204
|
+
maybeLayer.value.RIn,
|
|
3205
|
+
true
|
|
3206
|
+
);
|
|
3207
|
+
return new GraphNodeLeaf(ctx.nextId(), node, outTypes, inTypes);
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
return yield* fail(new UnableToProduceLayerGraphError(node.getText()));
|
|
3211
|
+
});
|
|
3212
|
+
}
|
|
3213
|
+
function findInnermostGraphEdge(graph, kind, key) {
|
|
3214
|
+
switch (graph._tag) {
|
|
3215
|
+
case "GraphNodeLeaf":
|
|
3216
|
+
return graph[kind].indexOf(key) > -1 ? [graph] : [];
|
|
3217
|
+
case "GraphNodeCompoundTransform": {
|
|
3218
|
+
if (graph[kind].indexOf(key) > -1) {
|
|
3219
|
+
let result = [];
|
|
3220
|
+
for (const child of graph.args) {
|
|
3221
|
+
result = result.concat(findInnermostGraphEdge(child, kind, key));
|
|
3222
|
+
}
|
|
3223
|
+
if (result.length > 0) return result;
|
|
3224
|
+
return [graph];
|
|
3225
|
+
}
|
|
3226
|
+
return [];
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
function escapeMermaid(text) {
|
|
3231
|
+
return text.replace(/"/mg, "#quot;").replace(/\n/mg, " ");
|
|
3232
|
+
}
|
|
3233
|
+
function processNodeMermaid(graph, ctx, ctxL) {
|
|
3234
|
+
return gen2(function* () {
|
|
3235
|
+
const ts = yield* service(TypeScriptApi);
|
|
3236
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3237
|
+
let subgraphDefs = [];
|
|
3238
|
+
if (!ctx.seenIds.has(graph.id)) {
|
|
3239
|
+
const subgraphsIn = [];
|
|
3240
|
+
for (const serviceId of graph.rin) {
|
|
3241
|
+
const type = ctxL.services.get(serviceId);
|
|
3242
|
+
const typeString = typeChecker.typeToString(type, void 0, ts.TypeFormatFlags.NoTruncation);
|
|
3243
|
+
subgraphsIn.push("subgraph " + graph.id + "_rin_" + serviceId + ' ["`' + escapeMermaid(typeString) + '`"]');
|
|
3244
|
+
subgraphsIn.push("end");
|
|
3245
|
+
}
|
|
3246
|
+
const subgraphsOut = [];
|
|
3247
|
+
for (const serviceId of graph.rout) {
|
|
3248
|
+
const type = ctxL.services.get(serviceId);
|
|
3249
|
+
const typeString = typeChecker.typeToString(type, void 0, ts.TypeFormatFlags.NoTruncation);
|
|
3250
|
+
subgraphsOut.push("subgraph " + graph.id + "_rout_" + serviceId + ' ["`' + escapeMermaid(typeString) + '`"]');
|
|
3251
|
+
subgraphsOut.push("end");
|
|
3252
|
+
}
|
|
3253
|
+
const sourceFile = graph.node.getSourceFile();
|
|
3254
|
+
const nodePosition = graph.node.getStart(sourceFile, false);
|
|
3255
|
+
const { character, line } = ts.getLineAndCharacterOfPosition(sourceFile, nodePosition);
|
|
3256
|
+
if (subgraphsIn.length > 0) {
|
|
3257
|
+
subgraphDefs = [
|
|
3258
|
+
...subgraphDefs,
|
|
3259
|
+
"subgraph " + graph.id + "_rin [Requires]",
|
|
3260
|
+
...subgraphsIn,
|
|
3261
|
+
"end",
|
|
3262
|
+
"style " + graph.id + "_rin stroke:none"
|
|
3263
|
+
];
|
|
3264
|
+
}
|
|
3265
|
+
if (subgraphsOut.length > 0) {
|
|
3266
|
+
subgraphDefs = [
|
|
3267
|
+
...subgraphDefs,
|
|
3268
|
+
"subgraph " + graph.id + "_rout [Provides]",
|
|
3269
|
+
...subgraphsOut,
|
|
3270
|
+
"end",
|
|
3271
|
+
"style " + graph.id + "_rout stroke:none"
|
|
3272
|
+
];
|
|
3273
|
+
}
|
|
3274
|
+
subgraphDefs = [
|
|
3275
|
+
"subgraph " + graph.id + ' ["`' + escapeMermaid(graph.node.getText()) + " _at ln " + (line + 1) + " col " + character + '_`"]',
|
|
3276
|
+
...subgraphDefs,
|
|
3277
|
+
"end",
|
|
3278
|
+
"style " + graph.id + " fill:transparent"
|
|
3279
|
+
];
|
|
3280
|
+
ctx.seenIds.add(graph.id);
|
|
3281
|
+
}
|
|
3282
|
+
switch (graph._tag) {
|
|
3283
|
+
case "GraphNodeLeaf": {
|
|
3284
|
+
return subgraphDefs;
|
|
3285
|
+
}
|
|
3286
|
+
case "GraphNodeCompoundTransform": {
|
|
3287
|
+
const childs = flatten(yield* all2(...graph.args.map((_) => processNodeMermaid(_, ctx, ctxL))));
|
|
3288
|
+
let currentEdges = [];
|
|
3289
|
+
const connectedNodes = /* @__PURE__ */ new Set();
|
|
3290
|
+
for (const requiredServiceKey of graph.rin) {
|
|
3291
|
+
for (const childNode of graph.args.filter((childNode2) => childNode2.rin.indexOf(requiredServiceKey) > -1)) {
|
|
3292
|
+
currentEdges = [
|
|
3293
|
+
...currentEdges,
|
|
3294
|
+
graph.id + "_rin_" + requiredServiceKey + " -.-> " + childNode.id + "_rin_" + requiredServiceKey
|
|
3295
|
+
];
|
|
3296
|
+
connectedNodes.add(childNode.id);
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
for (const providedServiceKey of graph.rout) {
|
|
3300
|
+
for (const childNode of graph.args.filter((childNode2) => childNode2.rout.indexOf(providedServiceKey) > -1)) {
|
|
3301
|
+
currentEdges = [
|
|
3302
|
+
...currentEdges,
|
|
3303
|
+
graph.id + "_rout_" + providedServiceKey + " -.-> " + childNode.id + "_rout_" + providedServiceKey
|
|
3304
|
+
];
|
|
3305
|
+
connectedNodes.add(childNode.id);
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
for (const childNode of graph.args) {
|
|
3309
|
+
if (!connectedNodes.has(childNode.id)) {
|
|
3310
|
+
currentEdges = [...currentEdges, graph.id + " -.-x " + childNode.id];
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
return [...subgraphDefs, ...childs, ...currentEdges];
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
});
|
|
3317
|
+
}
|
|
3318
|
+
function generateMarmaidUri(graph, ctxL) {
|
|
3319
|
+
return gen2(function* () {
|
|
3320
|
+
const ctx = {
|
|
3321
|
+
seenIds: /* @__PURE__ */ new Set()
|
|
3322
|
+
};
|
|
3323
|
+
const lines = yield* processNodeMermaid(graph, ctx, ctxL);
|
|
3324
|
+
const code = "flowchart TB\n" + lines.join("\n");
|
|
3325
|
+
const state = btoa(JSON.stringify({ code }));
|
|
3326
|
+
return "https://www.mermaidchart.com/play#" + state;
|
|
3327
|
+
});
|
|
3328
|
+
}
|
|
3329
|
+
function layerInfo(sourceFile, position, quickInfo2) {
|
|
3330
|
+
return pipe(
|
|
3331
|
+
gen2(function* () {
|
|
3332
|
+
const ts = yield* service(TypeScriptApi);
|
|
3333
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3334
|
+
const range = toTextRange(position);
|
|
3335
|
+
const maybeNode = pipe(
|
|
3336
|
+
yield* getAncestorNodesInRange(sourceFile, range),
|
|
3337
|
+
filter((_) => ts.isVariableDeclaration(_) || ts.isPropertyDeclaration(_)),
|
|
3338
|
+
filter((_) => isNodeInRange(range)(_.name)),
|
|
3339
|
+
head
|
|
3340
|
+
);
|
|
3341
|
+
if (isNone2(maybeNode)) return quickInfo2;
|
|
3342
|
+
const node = maybeNode.value;
|
|
3343
|
+
const layerNode = node.initializer ? node.initializer : node;
|
|
3344
|
+
const layerType2 = typeChecker.getTypeAtLocation(layerNode);
|
|
3345
|
+
const maybeLayer = yield* option(layerType(layerType2, layerNode));
|
|
3346
|
+
if (isNone2(maybeLayer)) return quickInfo2;
|
|
3347
|
+
let lastId = 0;
|
|
3348
|
+
const graphCtx = {
|
|
3349
|
+
services: /* @__PURE__ */ new Map(),
|
|
3350
|
+
serviceTypeToString: /* @__PURE__ */ new Map(),
|
|
3351
|
+
nextId: () => "id" + lastId++
|
|
3352
|
+
};
|
|
3353
|
+
const layerInfoDisplayParts = yield* pipe(
|
|
3354
|
+
processLayerGraphNode(graphCtx, layerNode, void 0),
|
|
3355
|
+
flatMap3(
|
|
3356
|
+
(rootNode) => gen2(function* () {
|
|
3357
|
+
yield* succeed(void 0);
|
|
3358
|
+
const lines = [];
|
|
3359
|
+
const appendInfo = (providesNode, type, kindText) => {
|
|
3360
|
+
const typeString = typeChecker.typeToString(
|
|
3361
|
+
type,
|
|
3362
|
+
void 0,
|
|
3363
|
+
ts.TypeFormatFlags.NoTruncation
|
|
3364
|
+
);
|
|
3365
|
+
const positions = providesNode.map((_) => {
|
|
3366
|
+
const nodePosition = _.node.getStart(sourceFile, false);
|
|
3367
|
+
const { character, line } = ts.getLineAndCharacterOfPosition(sourceFile, nodePosition);
|
|
3368
|
+
const nodeText = _.node.getText().trim().substr(0, 100);
|
|
3369
|
+
return "ln " + (line + 1) + " col " + character + " by `" + nodeText + "`";
|
|
3370
|
+
});
|
|
3371
|
+
lines.push("- " + typeString + " " + kindText + " at " + positions.join(", "));
|
|
3372
|
+
};
|
|
3373
|
+
for (const providesKey of rootNode.rout) {
|
|
3374
|
+
const providesNode = findInnermostGraphEdge(rootNode, "rout", providesKey);
|
|
3375
|
+
appendInfo(providesNode, graphCtx.services.get(providesKey), "provided");
|
|
3376
|
+
}
|
|
3377
|
+
lines.push("");
|
|
3378
|
+
for (const requiresKey of rootNode.rin) {
|
|
3379
|
+
const requiresNode = findInnermostGraphEdge(rootNode, "rin", requiresKey);
|
|
3380
|
+
appendInfo(requiresNode, graphCtx.services.get(requiresKey), "required");
|
|
3381
|
+
}
|
|
3382
|
+
const mermaidUri = yield* option(generateMarmaidUri(rootNode, graphCtx));
|
|
3383
|
+
const linkParts = [];
|
|
3384
|
+
if (isSome2(mermaidUri)) {
|
|
3385
|
+
linkParts.push({ kind: "space", text: "\n" });
|
|
3386
|
+
linkParts.push({ kind: "link", text: "{@link " });
|
|
3387
|
+
linkParts.push({ kind: "linkText", text: mermaidUri.value + " Show full Layer graph" });
|
|
3388
|
+
linkParts.push({ kind: "link", text: "}" });
|
|
3389
|
+
linkParts.push({ kind: "space", text: "\n" });
|
|
3390
|
+
}
|
|
3391
|
+
return [
|
|
3392
|
+
{
|
|
3393
|
+
kind: "text",
|
|
3394
|
+
text: "```\n/**\n" + lines.map((l) => " * " + l).join("\n") + "\n */\n```\n"
|
|
3395
|
+
},
|
|
3396
|
+
...linkParts
|
|
3397
|
+
];
|
|
3398
|
+
})
|
|
3399
|
+
),
|
|
3400
|
+
orElse3(
|
|
3401
|
+
(e) => succeed([{
|
|
3402
|
+
kind: "text",
|
|
3403
|
+
text: "```\n/** layer graph not created: " + e.message + " */\n```\n"
|
|
3404
|
+
}])
|
|
3405
|
+
)
|
|
3406
|
+
);
|
|
3407
|
+
if (!quickInfo2) {
|
|
3408
|
+
const start = node.getStart();
|
|
3409
|
+
const end = node.getEnd();
|
|
3410
|
+
return {
|
|
3411
|
+
kind: ts.ScriptElementKind.callSignatureElement,
|
|
3412
|
+
kindModifiers: "",
|
|
3413
|
+
textSpan: { start, length: end - start },
|
|
3414
|
+
documentation: layerInfoDisplayParts
|
|
3415
|
+
};
|
|
3416
|
+
}
|
|
3417
|
+
if (quickInfo2.documentation) {
|
|
3418
|
+
return {
|
|
3419
|
+
...quickInfo2,
|
|
3420
|
+
documentation: quickInfo2.documentation.concat([{ kind: "space", text: "\n" }]).concat(layerInfoDisplayParts)
|
|
3421
|
+
};
|
|
3422
|
+
}
|
|
3423
|
+
return {
|
|
3424
|
+
...quickInfo2,
|
|
3425
|
+
documentation: layerInfoDisplayParts
|
|
3426
|
+
};
|
|
3427
|
+
}),
|
|
3428
|
+
orElse3(() => succeed(quickInfo2))
|
|
3429
|
+
);
|
|
3430
|
+
}
|
|
3431
|
+
|
|
3432
|
+
// src/quickinfo.ts
|
|
3433
|
+
function quickInfo(sourceFile, position, quickInfo2) {
|
|
3434
|
+
return gen2(function* () {
|
|
3435
|
+
const deduped = yield* dedupeJsDocs(quickInfo2);
|
|
3436
|
+
const withEffectTypeArgs = yield* effectTypeArgs(sourceFile, position, deduped);
|
|
3437
|
+
const withLayerInfo = yield* layerInfo(sourceFile, position, withEffectTypeArgs);
|
|
3438
|
+
return withLayerInfo;
|
|
3439
|
+
});
|
|
3440
|
+
}
|
|
3441
|
+
|
|
2925
3442
|
// src/refactors/asyncAwaitToGen.ts
|
|
2926
3443
|
var asyncAwaitToGen = createRefactor({
|
|
2927
3444
|
name: "asyncAwaitToGen",
|
|
@@ -3611,19 +4128,15 @@ var removeUnnecessaryEffectGen = createRefactor({
|
|
|
3611
4128
|
description: "Remove unnecessary Effect.gen",
|
|
3612
4129
|
apply: fn("removeUnnecessaryEffectGen.apply")(function* (sourceFile, textRange) {
|
|
3613
4130
|
for (const nodeToReplace of yield* getAncestorNodesInRange(sourceFile, textRange)) {
|
|
3614
|
-
const maybeNode = yield*
|
|
3615
|
-
effectGen(nodeToReplace),
|
|
3616
|
-
flatMap3(({ body }) => returnYieldEffectBlock(body)),
|
|
3617
|
-
option
|
|
3618
|
-
);
|
|
4131
|
+
const maybeNode = yield* option(unnecessaryEffectGen(nodeToReplace));
|
|
3619
4132
|
if (isNone2(maybeNode)) continue;
|
|
3620
|
-
const
|
|
4133
|
+
const replacementNode = maybeNode.value.replacementNode;
|
|
3621
4134
|
return {
|
|
3622
4135
|
kind: "refactor.rewrite.effect.removeUnnecessaryEffectGen",
|
|
3623
4136
|
description: "Remove unnecessary Effect.gen",
|
|
3624
4137
|
apply: gen2(function* () {
|
|
3625
4138
|
const changeTracker = yield* service(ChangeTracker);
|
|
3626
|
-
changeTracker.replaceNode(sourceFile, nodeToReplace,
|
|
4139
|
+
changeTracker.replaceNode(sourceFile, nodeToReplace, yield* replacementNode);
|
|
3627
4140
|
})
|
|
3628
4141
|
};
|
|
3629
4142
|
}
|
|
@@ -4558,27 +5071,25 @@ var init = (modules) => {
|
|
|
4558
5071
|
);
|
|
4559
5072
|
};
|
|
4560
5073
|
proxy.getQuickInfoAtPosition = (fileName, position, ...args) => {
|
|
4561
|
-
const
|
|
5074
|
+
const applicableQuickInfo = languageService.getQuickInfoAtPosition(fileName, position, ...args);
|
|
4562
5075
|
if (languageServicePluginOptions.quickinfo) {
|
|
4563
|
-
const dedupedTagsQuickInfo = dedupeJsDocTags(quickInfo);
|
|
4564
5076
|
const program = languageService.getProgram();
|
|
4565
5077
|
if (program) {
|
|
4566
5078
|
const sourceFile = program.getSourceFile(fileName);
|
|
4567
5079
|
if (sourceFile) {
|
|
4568
5080
|
return pipe(
|
|
4569
|
-
|
|
5081
|
+
quickInfo(
|
|
4570
5082
|
sourceFile,
|
|
4571
5083
|
position,
|
|
4572
|
-
|
|
5084
|
+
applicableQuickInfo
|
|
4573
5085
|
),
|
|
4574
5086
|
runNano(program),
|
|
4575
|
-
Either_exports.getOrElse(() =>
|
|
5087
|
+
Either_exports.getOrElse(() => applicableQuickInfo)
|
|
4576
5088
|
);
|
|
4577
5089
|
}
|
|
4578
5090
|
}
|
|
4579
|
-
return dedupedTagsQuickInfo;
|
|
4580
5091
|
}
|
|
4581
|
-
return
|
|
5092
|
+
return applicableQuickInfo;
|
|
4582
5093
|
};
|
|
4583
5094
|
proxy.getCompletionsAtPosition = (fileName, position, options, formattingSettings, ...args) => {
|
|
4584
5095
|
const applicableCompletions = languageService.getCompletionsAtPosition(
|