@effect/language-service 0.20.0 → 0.21.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 +3 -2
- package/index.js +852 -615
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +674 -446
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -489,6 +489,7 @@ function compareBoth(self, that) {
|
|
|
489
489
|
return structuralRegionState.enabled && structuralRegionState.tester ? structuralRegionState.tester(self, that) : false;
|
|
490
490
|
}
|
|
491
491
|
var isEqual = (u) => hasProperty(u, symbol2);
|
|
492
|
+
var equivalence = () => equals;
|
|
492
493
|
|
|
493
494
|
// node_modules/.pnpm/effect@3.16.5/node_modules/effect/dist/esm/Inspectable.js
|
|
494
495
|
var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
@@ -947,6 +948,20 @@ var sort = /* @__PURE__ */ dual(2, (self, O) => {
|
|
|
947
948
|
out.sort(O);
|
|
948
949
|
return out;
|
|
949
950
|
});
|
|
951
|
+
var containsWith = (isEquivalent) => dual(2, (self, a) => {
|
|
952
|
+
for (const i of self) {
|
|
953
|
+
if (isEquivalent(a, i)) {
|
|
954
|
+
return true;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
return false;
|
|
958
|
+
});
|
|
959
|
+
var _equivalence = /* @__PURE__ */ equivalence();
|
|
960
|
+
var intersectionWith = (isEquivalent) => {
|
|
961
|
+
const has = containsWith(isEquivalent);
|
|
962
|
+
return dual(2, (self, that) => fromIterable(self).filter((a) => has(that, a)));
|
|
963
|
+
};
|
|
964
|
+
var intersection = /* @__PURE__ */ intersectionWith(_equivalence);
|
|
950
965
|
var empty = () => [];
|
|
951
966
|
var map3 = /* @__PURE__ */ dual(2, (self, f) => self.map(f));
|
|
952
967
|
var flatMap2 = /* @__PURE__ */ dual(2, (self, f) => {
|
|
@@ -1039,7 +1054,8 @@ function make3(run2) {
|
|
|
1039
1054
|
return result;
|
|
1040
1055
|
}
|
|
1041
1056
|
var unsafeRun = (fa) => {
|
|
1042
|
-
const
|
|
1057
|
+
const program = provideService(internalNanoCache, {})(fa);
|
|
1058
|
+
const result = program.run(contextEmpty);
|
|
1043
1059
|
switch (result._tag) {
|
|
1044
1060
|
case "Left":
|
|
1045
1061
|
return left2(result.value);
|
|
@@ -1076,14 +1092,14 @@ var orElse3 = (f) => (fa) => make3((ctx) => {
|
|
|
1076
1092
|
});
|
|
1077
1093
|
var firstSuccessOf = (arr) => arr.slice(1).reduce((arr2, fa) => orElse3(() => fa)(arr2), arr[0]);
|
|
1078
1094
|
var service = (tag) => make3(
|
|
1079
|
-
(ctx) => tag.key in ctx.value ?
|
|
1095
|
+
(ctx) => tag.key in ctx.value ? ctx.value[tag.key] : makeInternalDefect(`Cannot find service ${tag.key}`)
|
|
1080
1096
|
);
|
|
1081
1097
|
var provideService = (tag, value) => (fa) => make3((ctx) => {
|
|
1082
1098
|
return fa.run({
|
|
1083
1099
|
...ctx,
|
|
1084
1100
|
value: {
|
|
1085
1101
|
...ctx.value,
|
|
1086
|
-
[tag.key]: value
|
|
1102
|
+
[tag.key]: makeInternalSuccess(value)
|
|
1087
1103
|
}
|
|
1088
1104
|
});
|
|
1089
1105
|
});
|
|
@@ -1124,14 +1140,41 @@ var option = (fa) => make3((ctx) => {
|
|
|
1124
1140
|
return result;
|
|
1125
1141
|
}
|
|
1126
1142
|
});
|
|
1127
|
-
var
|
|
1143
|
+
var successUndefined = makeInternalSuccess(void 0);
|
|
1144
|
+
var void_2 = make3(() => successUndefined);
|
|
1145
|
+
var ignore = (fa) => make3((ctx) => {
|
|
1146
|
+
fa.run(ctx);
|
|
1147
|
+
return successUndefined;
|
|
1148
|
+
});
|
|
1149
|
+
var all2 = (...args) => make3((ctx) => {
|
|
1128
1150
|
const results = [];
|
|
1129
1151
|
for (const arg of args) {
|
|
1130
|
-
const result =
|
|
1131
|
-
|
|
1152
|
+
const result = arg.run(ctx);
|
|
1153
|
+
if (result._tag !== "Right") return result;
|
|
1154
|
+
results.push(result.value);
|
|
1132
1155
|
}
|
|
1133
|
-
return results;
|
|
1156
|
+
return makeInternalSuccess(results);
|
|
1134
1157
|
});
|
|
1158
|
+
var internalNanoCache = Tag(
|
|
1159
|
+
"@effect/language-service/internalNanoCache"
|
|
1160
|
+
);
|
|
1161
|
+
function cachedBy(fa, key, lookupKey) {
|
|
1162
|
+
return (...args) => make3((ctx) => {
|
|
1163
|
+
const cacheObj = ctx.value[internalNanoCache.key];
|
|
1164
|
+
let cache = cacheObj[key];
|
|
1165
|
+
if (!cache) {
|
|
1166
|
+
cache = /* @__PURE__ */ new Map();
|
|
1167
|
+
cacheObj[key] = cache;
|
|
1168
|
+
}
|
|
1169
|
+
const lookup = lookupKey(...args);
|
|
1170
|
+
if (cache.has(lookup)) {
|
|
1171
|
+
return cache.get(lookup);
|
|
1172
|
+
}
|
|
1173
|
+
const result = fa(...args).run(ctx);
|
|
1174
|
+
cache.set(lookup, result);
|
|
1175
|
+
return result;
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1135
1178
|
|
|
1136
1179
|
// src/core/TypeScriptApi.ts
|
|
1137
1180
|
var TypeScriptApi = Tag("TypeScriptApi");
|
|
@@ -1924,6 +1967,511 @@ var effectSelfInClasses = createCompletion({
|
|
|
1924
1967
|
})
|
|
1925
1968
|
});
|
|
1926
1969
|
|
|
1970
|
+
// src/core/TypeParser.ts
|
|
1971
|
+
var TypeParser = Tag("@effect/language-service/TypeParser");
|
|
1972
|
+
var TypeParserIssue = class _TypeParserIssue {
|
|
1973
|
+
_tag = "@effect/language-service/TypeParserIssue";
|
|
1974
|
+
static issue = fail(new _TypeParserIssue());
|
|
1975
|
+
};
|
|
1976
|
+
function make4(ts, typeChecker) {
|
|
1977
|
+
function typeParserIssue(_message, _type, _node) {
|
|
1978
|
+
return TypeParserIssue.issue;
|
|
1979
|
+
}
|
|
1980
|
+
function covariantTypeArgument(type) {
|
|
1981
|
+
const signatures = type.getCallSignatures();
|
|
1982
|
+
if (signatures.length !== 1) {
|
|
1983
|
+
return typeParserIssue("Covariant type has no call signature", type);
|
|
1984
|
+
}
|
|
1985
|
+
return succeed(signatures[0].getReturnType());
|
|
1986
|
+
}
|
|
1987
|
+
function contravariantTypeArgument(type) {
|
|
1988
|
+
const signatures = type.getCallSignatures();
|
|
1989
|
+
if (signatures.length !== 1) {
|
|
1990
|
+
return typeParserIssue("Contravariant type has no call signature", type);
|
|
1991
|
+
}
|
|
1992
|
+
return succeed(signatures[0].getTypeParameterAtPosition(0));
|
|
1993
|
+
}
|
|
1994
|
+
function invariantTypeArgument(type) {
|
|
1995
|
+
const signatures = type.getCallSignatures();
|
|
1996
|
+
if (signatures.length !== 1) {
|
|
1997
|
+
return typeParserIssue("Invariant type has no call signature", type);
|
|
1998
|
+
}
|
|
1999
|
+
return succeed(signatures[0].getReturnType());
|
|
2000
|
+
}
|
|
2001
|
+
const pipeableType = cachedBy(
|
|
2002
|
+
fn("TypeParser.pipeableType")(function* (type, atLocation) {
|
|
2003
|
+
const pipeSymbol = typeChecker.getPropertyOfType(type, "pipe");
|
|
2004
|
+
if (!pipeSymbol) {
|
|
2005
|
+
return yield* typeParserIssue("Type has no 'pipe' property", type, atLocation);
|
|
2006
|
+
}
|
|
2007
|
+
const pipeType = typeChecker.getTypeOfSymbolAtLocation(pipeSymbol, atLocation);
|
|
2008
|
+
const signatures = pipeType.getCallSignatures();
|
|
2009
|
+
if (signatures.length === 0) {
|
|
2010
|
+
return yield* typeParserIssue("'pipe' property is not callable", type, atLocation);
|
|
2011
|
+
}
|
|
2012
|
+
return type;
|
|
2013
|
+
}),
|
|
2014
|
+
"TypeParser.pipeableType",
|
|
2015
|
+
(type) => type
|
|
2016
|
+
);
|
|
2017
|
+
const varianceStructCovariantType = (type, atLocation, propertyName) => {
|
|
2018
|
+
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
2019
|
+
if (!propertySymbol) {
|
|
2020
|
+
return typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
2021
|
+
}
|
|
2022
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2023
|
+
return covariantTypeArgument(propertyType);
|
|
2024
|
+
};
|
|
2025
|
+
const varianceStructContravariantType = (type, atLocation, propertyName) => {
|
|
2026
|
+
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
2027
|
+
if (!propertySymbol) {
|
|
2028
|
+
return typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
2029
|
+
}
|
|
2030
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2031
|
+
return contravariantTypeArgument(propertyType);
|
|
2032
|
+
};
|
|
2033
|
+
const varianceStructInvariantType = (type, atLocation, propertyName) => {
|
|
2034
|
+
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
2035
|
+
if (!propertySymbol) {
|
|
2036
|
+
return typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
2037
|
+
}
|
|
2038
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2039
|
+
return invariantTypeArgument(propertyType);
|
|
2040
|
+
};
|
|
2041
|
+
const effectVarianceStruct = (type, atLocation) => map4(
|
|
2042
|
+
all2(
|
|
2043
|
+
varianceStructCovariantType(type, atLocation, "_A"),
|
|
2044
|
+
varianceStructCovariantType(type, atLocation, "_E"),
|
|
2045
|
+
varianceStructCovariantType(type, atLocation, "_R")
|
|
2046
|
+
),
|
|
2047
|
+
([A, E, R]) => ({ A, E, R })
|
|
2048
|
+
);
|
|
2049
|
+
const layerVarianceStruct = (type, atLocation) => map4(
|
|
2050
|
+
all2(
|
|
2051
|
+
varianceStructContravariantType(type, atLocation, "_ROut"),
|
|
2052
|
+
varianceStructCovariantType(type, atLocation, "_E"),
|
|
2053
|
+
varianceStructCovariantType(type, atLocation, "_RIn")
|
|
2054
|
+
),
|
|
2055
|
+
([ROut, E, RIn]) => ({ ROut, E, RIn })
|
|
2056
|
+
);
|
|
2057
|
+
const effectType = cachedBy(
|
|
2058
|
+
fn("TypeParser.effectType")(function* (type, atLocation) {
|
|
2059
|
+
yield* pipeableType(type, atLocation);
|
|
2060
|
+
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2061
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2062
|
+
);
|
|
2063
|
+
propertiesSymbols.sort((a, b) => b.name.indexOf("EffectTypeId") - a.name.indexOf("EffectTypeId"));
|
|
2064
|
+
for (const propertySymbol of propertiesSymbols) {
|
|
2065
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2066
|
+
const varianceArgs = yield* option(effectVarianceStruct(
|
|
2067
|
+
propertyType,
|
|
2068
|
+
atLocation
|
|
2069
|
+
));
|
|
2070
|
+
if (isSome2(varianceArgs)) {
|
|
2071
|
+
return varianceArgs.value;
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
|
|
2075
|
+
}),
|
|
2076
|
+
"TypeParser.effectType",
|
|
2077
|
+
(type) => type
|
|
2078
|
+
);
|
|
2079
|
+
const layerType = cachedBy(
|
|
2080
|
+
fn("TypeParser.layerType")(function* (type, atLocation) {
|
|
2081
|
+
yield* pipeableType(type, atLocation);
|
|
2082
|
+
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2083
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2084
|
+
);
|
|
2085
|
+
propertiesSymbols.sort((a, b) => b.name.indexOf("LayerTypeId") - a.name.indexOf("LayerTypeId"));
|
|
2086
|
+
for (const propertySymbol of propertiesSymbols) {
|
|
2087
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2088
|
+
const varianceArgs = yield* option(layerVarianceStruct(
|
|
2089
|
+
propertyType,
|
|
2090
|
+
atLocation
|
|
2091
|
+
));
|
|
2092
|
+
if (isSome2(varianceArgs)) {
|
|
2093
|
+
return varianceArgs.value;
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
return yield* typeParserIssue("Type has no layer variance struct", type, atLocation);
|
|
2097
|
+
}),
|
|
2098
|
+
"TypeParser.layerType",
|
|
2099
|
+
(type) => type
|
|
2100
|
+
);
|
|
2101
|
+
const fiberType = cachedBy(
|
|
2102
|
+
fn("TypeParser.fiberType")(function* (type, atLocation) {
|
|
2103
|
+
const awaitSymbol = typeChecker.getPropertyOfType(type, "await");
|
|
2104
|
+
const pollSymbol = typeChecker.getPropertyOfType(type, "poll");
|
|
2105
|
+
if (!awaitSymbol || !pollSymbol) {
|
|
2106
|
+
return yield* typeParserIssue(
|
|
2107
|
+
"Type is not a fiber because it does not have 'await' or 'poll' property",
|
|
2108
|
+
type,
|
|
2109
|
+
atLocation
|
|
2110
|
+
);
|
|
2111
|
+
}
|
|
2112
|
+
return yield* effectType(type, atLocation);
|
|
2113
|
+
}),
|
|
2114
|
+
"TypeParser.fiberType",
|
|
2115
|
+
(type) => type
|
|
2116
|
+
);
|
|
2117
|
+
const effectSubtype = cachedBy(
|
|
2118
|
+
fn("TypeParser.effectSubtype")(function* (type, atLocation) {
|
|
2119
|
+
const tagSymbol = typeChecker.getPropertyOfType(type, "_tag");
|
|
2120
|
+
const getSymbol = typeChecker.getPropertyOfType(type, "get");
|
|
2121
|
+
if (!(tagSymbol || getSymbol)) {
|
|
2122
|
+
return yield* typeParserIssue(
|
|
2123
|
+
"Type is not a subtype of effect because it does not have '_tag' or 'get' property",
|
|
2124
|
+
type,
|
|
2125
|
+
atLocation
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2128
|
+
return yield* effectType(type, atLocation);
|
|
2129
|
+
}),
|
|
2130
|
+
"TypeParser.effectSubtype",
|
|
2131
|
+
(type) => type
|
|
2132
|
+
);
|
|
2133
|
+
const importedEffectModule = cachedBy(
|
|
2134
|
+
fn("TypeParser.importedEffectModule")(function* (node) {
|
|
2135
|
+
const type = typeChecker.getTypeAtLocation(node);
|
|
2136
|
+
const propertySymbol = typeChecker.getPropertyOfType(type, "never");
|
|
2137
|
+
if (!propertySymbol) {
|
|
2138
|
+
return yield* typeParserIssue("Type has no 'never' property", type, node);
|
|
2139
|
+
}
|
|
2140
|
+
if (!ts.isExpression(node)) {
|
|
2141
|
+
return yield* typeParserIssue("Node is not an expression", type, node);
|
|
2142
|
+
}
|
|
2143
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, node);
|
|
2144
|
+
yield* effectType(propertyType, node);
|
|
2145
|
+
return node;
|
|
2146
|
+
}),
|
|
2147
|
+
"TypeParser.importedEffectModule",
|
|
2148
|
+
(node) => node
|
|
2149
|
+
);
|
|
2150
|
+
const effectGen = cachedBy(
|
|
2151
|
+
fn("TypeParser.effectGen")(function* (node) {
|
|
2152
|
+
if (!ts.isCallExpression(node)) {
|
|
2153
|
+
return yield* typeParserIssue("Node is not a call expression", void 0, node);
|
|
2154
|
+
}
|
|
2155
|
+
if (node.arguments.length === 0) {
|
|
2156
|
+
return yield* typeParserIssue("Node has no arguments", void 0, node);
|
|
2157
|
+
}
|
|
2158
|
+
const generatorFunction = node.arguments[0];
|
|
2159
|
+
if (!ts.isFunctionExpression(generatorFunction)) {
|
|
2160
|
+
return yield* typeParserIssue("Node is not a function expression", void 0, node);
|
|
2161
|
+
}
|
|
2162
|
+
if (generatorFunction.asteriskToken === void 0) {
|
|
2163
|
+
return yield* typeParserIssue("Node is not a generator function", void 0, node);
|
|
2164
|
+
}
|
|
2165
|
+
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
2166
|
+
return yield* typeParserIssue("Node is not a property access expression", void 0, node);
|
|
2167
|
+
}
|
|
2168
|
+
const propertyAccess = node.expression;
|
|
2169
|
+
if (propertyAccess.name.text !== "gen") {
|
|
2170
|
+
return yield* typeParserIssue("Call expression name is not 'gen'", void 0, node);
|
|
2171
|
+
}
|
|
2172
|
+
const effectModule = yield* importedEffectModule(propertyAccess.expression);
|
|
2173
|
+
return {
|
|
2174
|
+
node,
|
|
2175
|
+
effectModule,
|
|
2176
|
+
generatorFunction,
|
|
2177
|
+
body: generatorFunction.body,
|
|
2178
|
+
functionStar: generatorFunction.getFirstToken()
|
|
2179
|
+
};
|
|
2180
|
+
}),
|
|
2181
|
+
"TypeParser.effectGen",
|
|
2182
|
+
(node) => node
|
|
2183
|
+
);
|
|
2184
|
+
const effectFnUntracedGen = cachedBy(
|
|
2185
|
+
fn("TypeParser.effectFnUntracedGen")(
|
|
2186
|
+
function* (node) {
|
|
2187
|
+
if (!ts.isCallExpression(node)) {
|
|
2188
|
+
return yield* typeParserIssue("Node is not a call expression", void 0, node);
|
|
2189
|
+
}
|
|
2190
|
+
if (node.arguments.length === 0) {
|
|
2191
|
+
return yield* typeParserIssue("Node has no arguments", void 0, node);
|
|
2192
|
+
}
|
|
2193
|
+
const generatorFunction = node.arguments[0];
|
|
2194
|
+
if (!ts.isFunctionExpression(generatorFunction)) {
|
|
2195
|
+
return yield* typeParserIssue("Node is not a function expression", void 0, node);
|
|
2196
|
+
}
|
|
2197
|
+
if (generatorFunction.asteriskToken === void 0) {
|
|
2198
|
+
return yield* typeParserIssue(
|
|
2199
|
+
"Node is not a generator function",
|
|
2200
|
+
void 0,
|
|
2201
|
+
node
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
2205
|
+
return yield* typeParserIssue(
|
|
2206
|
+
"Node is not a property access expression",
|
|
2207
|
+
void 0,
|
|
2208
|
+
node
|
|
2209
|
+
);
|
|
2210
|
+
}
|
|
2211
|
+
const propertyAccess = node.expression;
|
|
2212
|
+
if (propertyAccess.name.text !== "fnUntraced") {
|
|
2213
|
+
return yield* typeParserIssue(
|
|
2214
|
+
"Call expression name is not 'fnUntraced'",
|
|
2215
|
+
void 0,
|
|
2216
|
+
node
|
|
2217
|
+
);
|
|
2218
|
+
}
|
|
2219
|
+
const effectModule = yield* importedEffectModule(propertyAccess.expression);
|
|
2220
|
+
return {
|
|
2221
|
+
node,
|
|
2222
|
+
effectModule,
|
|
2223
|
+
generatorFunction,
|
|
2224
|
+
body: generatorFunction.body,
|
|
2225
|
+
functionStar: generatorFunction.getFirstToken()
|
|
2226
|
+
};
|
|
2227
|
+
}
|
|
2228
|
+
),
|
|
2229
|
+
"TypeParser.effectFnUntracedGen",
|
|
2230
|
+
(node) => node
|
|
2231
|
+
);
|
|
2232
|
+
const effectFnGen = cachedBy(
|
|
2233
|
+
fn("TypeParser.effectFnGen")(function* (node) {
|
|
2234
|
+
if (!ts.isCallExpression(node)) {
|
|
2235
|
+
return yield* typeParserIssue("Node is not a call expression", void 0, node);
|
|
2236
|
+
}
|
|
2237
|
+
if (node.arguments.length === 0) {
|
|
2238
|
+
return yield* typeParserIssue("Node has no arguments", void 0, node);
|
|
2239
|
+
}
|
|
2240
|
+
const generatorFunction = node.arguments[0];
|
|
2241
|
+
if (!ts.isFunctionExpression(generatorFunction)) {
|
|
2242
|
+
return yield* typeParserIssue(
|
|
2243
|
+
"Node is not a function expression",
|
|
2244
|
+
void 0,
|
|
2245
|
+
node
|
|
2246
|
+
);
|
|
2247
|
+
}
|
|
2248
|
+
if (generatorFunction.asteriskToken === void 0) {
|
|
2249
|
+
return yield* typeParserIssue(
|
|
2250
|
+
"Node is not a generator function",
|
|
2251
|
+
void 0,
|
|
2252
|
+
node
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
|
|
2256
|
+
if (!ts.isPropertyAccessExpression(expressionToTest)) {
|
|
2257
|
+
return yield* typeParserIssue(
|
|
2258
|
+
"Node is not a property access expression",
|
|
2259
|
+
void 0,
|
|
2260
|
+
node
|
|
2261
|
+
);
|
|
2262
|
+
}
|
|
2263
|
+
const propertyAccess = expressionToTest;
|
|
2264
|
+
if (propertyAccess.name.text !== "fn") {
|
|
2265
|
+
return yield* typeParserIssue(
|
|
2266
|
+
"Call expression name is not 'fn'",
|
|
2267
|
+
void 0,
|
|
2268
|
+
node
|
|
2269
|
+
);
|
|
2270
|
+
}
|
|
2271
|
+
const effectModule = yield* importedEffectModule(propertyAccess.expression);
|
|
2272
|
+
return {
|
|
2273
|
+
node,
|
|
2274
|
+
generatorFunction,
|
|
2275
|
+
effectModule,
|
|
2276
|
+
body: generatorFunction.body,
|
|
2277
|
+
functionStar: generatorFunction.getFirstToken()
|
|
2278
|
+
};
|
|
2279
|
+
}),
|
|
2280
|
+
"TypeParser.effectFnGen",
|
|
2281
|
+
(node) => node
|
|
2282
|
+
);
|
|
2283
|
+
const unnecessaryEffectGen2 = cachedBy(
|
|
2284
|
+
fn("TypeParser.unnecessaryEffectGen")(function* (node) {
|
|
2285
|
+
const { body } = yield* effectGen(node);
|
|
2286
|
+
if (body.statements.length !== 1) {
|
|
2287
|
+
return yield* typeParserIssue(
|
|
2288
|
+
"Generator body should have a single statement",
|
|
2289
|
+
void 0,
|
|
2290
|
+
node
|
|
2291
|
+
);
|
|
2292
|
+
}
|
|
2293
|
+
let explicitReturn = false;
|
|
2294
|
+
let nodeToCheck = body.statements[0];
|
|
2295
|
+
while (nodeToCheck) {
|
|
2296
|
+
if (ts.isReturnStatement(nodeToCheck) && nodeToCheck.expression) {
|
|
2297
|
+
nodeToCheck = nodeToCheck.expression;
|
|
2298
|
+
explicitReturn = true;
|
|
2299
|
+
continue;
|
|
2300
|
+
}
|
|
2301
|
+
if (ts.isExpressionStatement(nodeToCheck)) {
|
|
2302
|
+
nodeToCheck = nodeToCheck.expression;
|
|
2303
|
+
continue;
|
|
2304
|
+
}
|
|
2305
|
+
if (ts.isYieldExpression(nodeToCheck) && nodeToCheck.asteriskToken && nodeToCheck.expression) {
|
|
2306
|
+
const yieldedExpression = nodeToCheck.expression;
|
|
2307
|
+
const type = typeChecker.getTypeAtLocation(yieldedExpression);
|
|
2308
|
+
const { A: successType } = yield* effectType(type, yieldedExpression);
|
|
2309
|
+
let replacementNode = succeed(yieldedExpression);
|
|
2310
|
+
if (!explicitReturn && !(successType.flags & ts.TypeFlags.VoidLike)) {
|
|
2311
|
+
replacementNode = pipe(
|
|
2312
|
+
gen2(function* () {
|
|
2313
|
+
const effectIdentifier = pipe(
|
|
2314
|
+
yield* option(
|
|
2315
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(node.getSourceFile(), "effect", "Effect")
|
|
2316
|
+
),
|
|
2317
|
+
match2({
|
|
2318
|
+
onNone: () => "Effect",
|
|
2319
|
+
onSome: (_) => _.text
|
|
2320
|
+
})
|
|
2321
|
+
);
|
|
2322
|
+
return ts.factory.createCallExpression(
|
|
2323
|
+
ts.factory.createPropertyAccessExpression(
|
|
2324
|
+
ts.factory.createIdentifier(effectIdentifier),
|
|
2325
|
+
"asVoid"
|
|
2326
|
+
),
|
|
2327
|
+
void 0,
|
|
2328
|
+
[
|
|
2329
|
+
yieldedExpression
|
|
2330
|
+
]
|
|
2331
|
+
);
|
|
2332
|
+
}),
|
|
2333
|
+
provideService(TypeScriptApi, ts)
|
|
2334
|
+
);
|
|
2335
|
+
}
|
|
2336
|
+
return { node, body, yieldedExpression, replacementNode };
|
|
2337
|
+
}
|
|
2338
|
+
break;
|
|
2339
|
+
}
|
|
2340
|
+
return yield* typeParserIssue(
|
|
2341
|
+
"Not an handled node",
|
|
2342
|
+
void 0,
|
|
2343
|
+
node
|
|
2344
|
+
);
|
|
2345
|
+
}),
|
|
2346
|
+
"TypeParser.unnecessaryEffectGen",
|
|
2347
|
+
(node) => node
|
|
2348
|
+
);
|
|
2349
|
+
const effectSchemaVarianceStruct = (type, atLocation) => map4(
|
|
2350
|
+
all2(
|
|
2351
|
+
varianceStructInvariantType(type, atLocation, "_A"),
|
|
2352
|
+
varianceStructInvariantType(type, atLocation, "_I"),
|
|
2353
|
+
varianceStructCovariantType(type, atLocation, "_R")
|
|
2354
|
+
),
|
|
2355
|
+
([A, I, R]) => ({ A, I, R })
|
|
2356
|
+
);
|
|
2357
|
+
const effectSchemaType = cachedBy(
|
|
2358
|
+
fn("TypeParser.effectSchemaType")(function* (type, atLocation) {
|
|
2359
|
+
yield* pipeableType(type, atLocation);
|
|
2360
|
+
const ast = typeChecker.getPropertyOfType(type, "ast");
|
|
2361
|
+
if (!ast) return yield* typeParserIssue("Has no 'ast' property", type, atLocation);
|
|
2362
|
+
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2363
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2364
|
+
);
|
|
2365
|
+
propertiesSymbols.sort((a, b) => b.name.indexOf("TypeId") - a.name.indexOf("TypeId"));
|
|
2366
|
+
for (const propertySymbol of propertiesSymbols) {
|
|
2367
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2368
|
+
const varianceArgs = yield* option(effectSchemaVarianceStruct(
|
|
2369
|
+
propertyType,
|
|
2370
|
+
atLocation
|
|
2371
|
+
));
|
|
2372
|
+
if (isSome2(varianceArgs)) {
|
|
2373
|
+
return varianceArgs.value;
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
return yield* typeParserIssue("Type has no schema variance struct", type, atLocation);
|
|
2377
|
+
}),
|
|
2378
|
+
"TypeParser.effectSchemaType",
|
|
2379
|
+
(type) => type
|
|
2380
|
+
);
|
|
2381
|
+
const contextTagVarianceStruct = (type, atLocation) => map4(
|
|
2382
|
+
all2(
|
|
2383
|
+
varianceStructInvariantType(type, atLocation, "_Identifier"),
|
|
2384
|
+
varianceStructInvariantType(type, atLocation, "_Service")
|
|
2385
|
+
),
|
|
2386
|
+
([Identifier, Service]) => ({ Identifier, Service })
|
|
2387
|
+
);
|
|
2388
|
+
const contextTag = cachedBy(
|
|
2389
|
+
fn("TypeParser.contextTag")(function* (type, atLocation) {
|
|
2390
|
+
yield* pipeableType(type, atLocation);
|
|
2391
|
+
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2392
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2393
|
+
);
|
|
2394
|
+
propertiesSymbols.sort((a, b) => b.name.indexOf("TypeId") - a.name.indexOf("TypeId"));
|
|
2395
|
+
for (const propertySymbol of propertiesSymbols) {
|
|
2396
|
+
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2397
|
+
const varianceArgs = yield* option(contextTagVarianceStruct(
|
|
2398
|
+
propertyType,
|
|
2399
|
+
atLocation
|
|
2400
|
+
));
|
|
2401
|
+
if (isSome2(varianceArgs)) {
|
|
2402
|
+
return varianceArgs.value;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
return yield* typeParserIssue("Type has no tag variance struct", type, atLocation);
|
|
2406
|
+
}),
|
|
2407
|
+
"TypeParser.contextTag",
|
|
2408
|
+
(type) => type
|
|
2409
|
+
);
|
|
2410
|
+
return {
|
|
2411
|
+
effectType,
|
|
2412
|
+
layerType,
|
|
2413
|
+
fiberType,
|
|
2414
|
+
effectSubtype,
|
|
2415
|
+
importedEffectModule,
|
|
2416
|
+
effectGen,
|
|
2417
|
+
effectFnUntracedGen,
|
|
2418
|
+
effectFnGen,
|
|
2419
|
+
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
2420
|
+
effectSchemaType,
|
|
2421
|
+
contextTag
|
|
2422
|
+
};
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
// src/completions/fnFunctionStar.ts
|
|
2426
|
+
var fnFunctionStar = createCompletion({
|
|
2427
|
+
name: "fnFunctionStar",
|
|
2428
|
+
apply: fn("fnFunctionStar")(function* (sourceFile, position) {
|
|
2429
|
+
const ts = yield* service(TypeScriptApi);
|
|
2430
|
+
const typeParser = yield* service(TypeParser);
|
|
2431
|
+
const maybeInfos = yield* option(
|
|
2432
|
+
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
2433
|
+
);
|
|
2434
|
+
if (isNone2(maybeInfos)) return [];
|
|
2435
|
+
const { accessedObject } = maybeInfos.value;
|
|
2436
|
+
const isEffectModule = yield* option(typeParser.importedEffectModule(accessedObject));
|
|
2437
|
+
if (isNone2(isEffectModule)) return [];
|
|
2438
|
+
const span = ts.createTextSpan(
|
|
2439
|
+
accessedObject.end + 1,
|
|
2440
|
+
Math.max(0, position - accessedObject.end - 1)
|
|
2441
|
+
);
|
|
2442
|
+
const maybeFnName = pipe(
|
|
2443
|
+
yield* getAncestorNodesInRange(sourceFile, toTextRange(accessedObject.pos)),
|
|
2444
|
+
filter(ts.isVariableDeclaration),
|
|
2445
|
+
map3((_) => _.name && ts.isIdentifier(_.name) ? _.name.text : ""),
|
|
2446
|
+
filter((_) => _.length > 0),
|
|
2447
|
+
head,
|
|
2448
|
+
map2((name) => [
|
|
2449
|
+
{
|
|
2450
|
+
name: `fn("${name}")`,
|
|
2451
|
+
kind: ts.ScriptElementKind.constElement,
|
|
2452
|
+
insertText: `fn("${name}")(function*(${"${1}"}){${"${0}"}})`,
|
|
2453
|
+
replacementSpan: span,
|
|
2454
|
+
isSnippet: true
|
|
2455
|
+
}
|
|
2456
|
+
]),
|
|
2457
|
+
getOrElse2(() => [])
|
|
2458
|
+
);
|
|
2459
|
+
return maybeFnName.concat([{
|
|
2460
|
+
name: `fn(function*(){})`,
|
|
2461
|
+
kind: ts.ScriptElementKind.constElement,
|
|
2462
|
+
insertText: `fn(function*(${"${1}"}){${"${0}"}})`,
|
|
2463
|
+
replacementSpan: span,
|
|
2464
|
+
isSnippet: true
|
|
2465
|
+
}, {
|
|
2466
|
+
name: `fnUntraced(function*(){})`,
|
|
2467
|
+
kind: ts.ScriptElementKind.constElement,
|
|
2468
|
+
insertText: `fnUntraced(function*(${"${1}"}){${"${0}"}})`,
|
|
2469
|
+
replacementSpan: span,
|
|
2470
|
+
isSnippet: true
|
|
2471
|
+
}]);
|
|
2472
|
+
})
|
|
2473
|
+
});
|
|
2474
|
+
|
|
1927
2475
|
// src/core/TypeCheckerApi.ts
|
|
1928
2476
|
var TypeCheckerApi = Tag("TypeChecker");
|
|
1929
2477
|
var TypeCheckerApiCache = Tag("TypeCheckerApiCache");
|
|
@@ -2076,549 +2624,104 @@ var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (so
|
|
|
2076
2624
|
const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
|
|
2077
2625
|
const realType = typeChecker.getTypeAtLocation(node);
|
|
2078
2626
|
result.push([node, expectedType, node, realType]);
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2084
|
-
continue;
|
|
2085
|
-
} else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
2086
|
-
const expectedType = typeChecker.getTypeAtLocation(node.left);
|
|
2087
|
-
const realType = typeChecker.getTypeAtLocation(node.right);
|
|
2088
|
-
result.push([node.left, expectedType, node.right, realType]);
|
|
2089
|
-
appendNodeToVisit(node.right);
|
|
2090
|
-
continue;
|
|
2091
|
-
} else if (ts.isReturnStatement(node) && node.expression) {
|
|
2092
|
-
const parentDeclaration = yield* option(getAncestorConvertibleDeclaration(node));
|
|
2093
|
-
if (isSome2(parentDeclaration)) {
|
|
2094
|
-
const expectedType = yield* option(getInferredReturnType(parentDeclaration.value));
|
|
2095
|
-
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2096
|
-
if (isSome2(expectedType)) {
|
|
2097
|
-
result.push([node, expectedType.value, node, realType]);
|
|
2098
|
-
}
|
|
2099
|
-
}
|
|
2100
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2101
|
-
continue;
|
|
2102
|
-
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length === 0 && ts.isExpression(node.body)) {
|
|
2103
|
-
const body = node.body;
|
|
2104
|
-
const expectedType = typeChecker.getContextualType(body);
|
|
2105
|
-
const realType = typeChecker.getTypeAtLocation(body);
|
|
2106
|
-
if (expectedType) {
|
|
2107
|
-
result.push([body, expectedType, body, realType]);
|
|
2108
|
-
}
|
|
2109
|
-
ts.forEachChild(body, appendNodeToVisit);
|
|
2110
|
-
continue;
|
|
2111
|
-
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length > 0 && ts.isExpression(node.body)) {
|
|
2112
|
-
const body = node.body;
|
|
2113
|
-
const expectedType = yield* option(getInferredReturnType(node));
|
|
2114
|
-
const realType = typeChecker.getTypeAtLocation(body);
|
|
2115
|
-
if (isSome2(expectedType)) {
|
|
2116
|
-
result.push([body, expectedType.value, body, realType]);
|
|
2117
|
-
}
|
|
2118
|
-
ts.forEachChild(body, appendNodeToVisit);
|
|
2119
|
-
continue;
|
|
2120
|
-
} else if (ts.isSatisfiesExpression(node)) {
|
|
2121
|
-
const expectedType = typeChecker.getTypeAtLocation(node.type);
|
|
2122
|
-
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2123
|
-
result.push([node.expression, expectedType, node.expression, realType]);
|
|
2124
|
-
appendNodeToVisit(node.expression);
|
|
2125
|
-
continue;
|
|
2126
|
-
}
|
|
2127
|
-
ts.forEachChild(node, appendNodeToVisit);
|
|
2128
|
-
}
|
|
2129
|
-
cache.expectedAndRealType.set(sourceFile, result);
|
|
2130
|
-
return result;
|
|
2131
|
-
});
|
|
2132
|
-
var appendToUniqueTypesMap = fn(
|
|
2133
|
-
"TypeCheckerApi.appendToUniqueTypesMap"
|
|
2134
|
-
)(
|
|
2135
|
-
function* (memory, initialType, excludeNever) {
|
|
2136
|
-
const ts = yield* service(TypeScriptApi);
|
|
2137
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2138
|
-
const newIndexes = /* @__PURE__ */ new Set();
|
|
2139
|
-
const knownIndexes = /* @__PURE__ */ new Set();
|
|
2140
|
-
let toTest = [initialType];
|
|
2141
|
-
while (toTest.length > 0) {
|
|
2142
|
-
const type = toTest.pop();
|
|
2143
|
-
if (!type) break;
|
|
2144
|
-
if (excludeNever && type.flags & ts.TypeFlags.Never) {
|
|
2145
|
-
continue;
|
|
2146
|
-
}
|
|
2147
|
-
if (type.isUnion()) {
|
|
2148
|
-
toTest = toTest.concat(type.types);
|
|
2149
|
-
} else {
|
|
2150
|
-
const foundMatch = [];
|
|
2151
|
-
for (const [typeId, knownType] of memory.entries()) {
|
|
2152
|
-
const areSame = typeChecker.isTypeAssignableTo(knownType, type) && typeChecker.isTypeAssignableTo(type, knownType);
|
|
2153
|
-
if (areSame) {
|
|
2154
|
-
foundMatch.push(typeId);
|
|
2155
|
-
break;
|
|
2156
|
-
}
|
|
2157
|
-
}
|
|
2158
|
-
if (foundMatch.length === 0) {
|
|
2159
|
-
const newId = "t" + (memory.size + 1);
|
|
2160
|
-
memory.set(newId, type);
|
|
2161
|
-
newIndexes.add(newId);
|
|
2162
|
-
} else {
|
|
2163
|
-
knownIndexes.add(foundMatch[0]);
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
return {
|
|
2168
|
-
newIndexes,
|
|
2169
|
-
knownIndexes,
|
|
2170
|
-
allIndexes: pipe(
|
|
2171
|
-
fromIterable(newIndexes),
|
|
2172
|
-
appendAll(fromIterable(knownIndexes))
|
|
2173
|
-
)
|
|
2174
|
-
};
|
|
2175
|
-
}
|
|
2176
|
-
);
|
|
2177
|
-
|
|
2178
|
-
// src/utils/TypeParser.ts
|
|
2179
|
-
var TypeParserIssue = class {
|
|
2180
|
-
constructor(type, node, message) {
|
|
2181
|
-
this.type = type;
|
|
2182
|
-
this.node = node;
|
|
2183
|
-
this.message = message;
|
|
2184
|
-
}
|
|
2185
|
-
_tag = "@effect/language-service/TypeParserIssue";
|
|
2186
|
-
};
|
|
2187
|
-
function typeParserIssue(message, type, node) {
|
|
2188
|
-
return fail(new TypeParserIssue(type, node, message));
|
|
2189
|
-
}
|
|
2190
|
-
function covariantTypeArgument(type) {
|
|
2191
|
-
const signatures = type.getCallSignatures();
|
|
2192
|
-
if (signatures.length !== 1) {
|
|
2193
|
-
return typeParserIssue("Covariant type has no call signature", type);
|
|
2194
|
-
}
|
|
2195
|
-
return succeed(signatures[0].getReturnType());
|
|
2196
|
-
}
|
|
2197
|
-
function contravariantTypeArgument(type) {
|
|
2198
|
-
const signatures = type.getCallSignatures();
|
|
2199
|
-
if (signatures.length !== 1) {
|
|
2200
|
-
return typeParserIssue("Contravariant type has no call signature", type);
|
|
2201
|
-
}
|
|
2202
|
-
return succeed(signatures[0].getTypeParameterAtPosition(0));
|
|
2203
|
-
}
|
|
2204
|
-
function invariantTypeArgument(type) {
|
|
2205
|
-
const signatures = type.getCallSignatures();
|
|
2206
|
-
if (signatures.length !== 1) {
|
|
2207
|
-
return typeParserIssue("Invariant type has no call signature", type);
|
|
2208
|
-
}
|
|
2209
|
-
return succeed(signatures[0].getReturnType());
|
|
2210
|
-
}
|
|
2211
|
-
var pipeableType = fn("TypeParser.pipeableType")(function* (type, atLocation) {
|
|
2212
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2213
|
-
const pipeSymbol = typeChecker.getPropertyOfType(type, "pipe");
|
|
2214
|
-
if (!pipeSymbol) {
|
|
2215
|
-
return yield* typeParserIssue("Type has no 'pipe' property", type, atLocation);
|
|
2216
|
-
}
|
|
2217
|
-
const pipeType = typeChecker.getTypeOfSymbolAtLocation(pipeSymbol, atLocation);
|
|
2218
|
-
const signatures = pipeType.getCallSignatures();
|
|
2219
|
-
if (signatures.length === 0) {
|
|
2220
|
-
return yield* typeParserIssue("'pipe' property is not callable", type, atLocation);
|
|
2221
|
-
}
|
|
2222
|
-
return type;
|
|
2223
|
-
});
|
|
2224
|
-
var varianceStructCovariantType = fn("TypeParser.varianceStructCovariantType")(
|
|
2225
|
-
function* (type, atLocation, propertyName) {
|
|
2226
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2227
|
-
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
2228
|
-
if (!propertySymbol) {
|
|
2229
|
-
return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
2230
|
-
}
|
|
2231
|
-
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2232
|
-
return yield* covariantTypeArgument(propertyType);
|
|
2233
|
-
}
|
|
2234
|
-
);
|
|
2235
|
-
var varianceStructContravariantType = fn(
|
|
2236
|
-
"TypeParser.varianceStructContravariantType"
|
|
2237
|
-
)(
|
|
2238
|
-
function* (type, atLocation, propertyName) {
|
|
2239
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2240
|
-
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
2241
|
-
if (!propertySymbol) {
|
|
2242
|
-
return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
2243
|
-
}
|
|
2244
|
-
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2245
|
-
return yield* contravariantTypeArgument(propertyType);
|
|
2246
|
-
}
|
|
2247
|
-
);
|
|
2248
|
-
var varianceStructInvariantType = fn("TypeParser.varianceStructInvariantType")(
|
|
2249
|
-
function* (type, atLocation, propertyName) {
|
|
2250
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2251
|
-
const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
|
|
2252
|
-
if (!propertySymbol) {
|
|
2253
|
-
return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
|
|
2254
|
-
}
|
|
2255
|
-
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2256
|
-
return yield* invariantTypeArgument(propertyType);
|
|
2257
|
-
}
|
|
2258
|
-
);
|
|
2259
|
-
var effectVarianceStruct = fn("TypeParser.effectVarianceStruct")(function* (type, atLocation) {
|
|
2260
|
-
return {
|
|
2261
|
-
A: yield* varianceStructCovariantType(type, atLocation, "_A"),
|
|
2262
|
-
E: yield* varianceStructCovariantType(type, atLocation, "_E"),
|
|
2263
|
-
R: yield* varianceStructCovariantType(type, atLocation, "_R")
|
|
2264
|
-
};
|
|
2265
|
-
});
|
|
2266
|
-
var layerVarianceStruct = fn("TypeParser.layerVarianceStruct")(function* (type, atLocation) {
|
|
2267
|
-
return {
|
|
2268
|
-
ROut: yield* varianceStructContravariantType(type, atLocation, "_ROut"),
|
|
2269
|
-
E: yield* varianceStructCovariantType(type, atLocation, "_E"),
|
|
2270
|
-
RIn: yield* varianceStructCovariantType(type, atLocation, "_RIn")
|
|
2271
|
-
};
|
|
2272
|
-
});
|
|
2273
|
-
var effectType = fn("TypeParser.effectType")(function* (type, atLocation) {
|
|
2274
|
-
const ts = yield* service(TypeScriptApi);
|
|
2275
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2276
|
-
yield* pipeableType(type, atLocation);
|
|
2277
|
-
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2278
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2279
|
-
);
|
|
2280
|
-
propertiesSymbols.sort((a, b) => b.name.indexOf("EffectTypeId") - a.name.indexOf("EffectTypeId"));
|
|
2281
|
-
for (const propertySymbol of propertiesSymbols) {
|
|
2282
|
-
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2283
|
-
const varianceArgs = yield* option(effectVarianceStruct(
|
|
2284
|
-
propertyType,
|
|
2285
|
-
atLocation
|
|
2286
|
-
));
|
|
2287
|
-
if (isSome2(varianceArgs)) {
|
|
2288
|
-
return varianceArgs.value;
|
|
2289
|
-
}
|
|
2290
|
-
}
|
|
2291
|
-
return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
|
|
2292
|
-
});
|
|
2293
|
-
var layerType = fn("TypeParser.layerType")(function* (type, atLocation) {
|
|
2294
|
-
const ts = yield* service(TypeScriptApi);
|
|
2295
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2296
|
-
yield* pipeableType(type, atLocation);
|
|
2297
|
-
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2298
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2299
|
-
);
|
|
2300
|
-
propertiesSymbols.sort((a, b) => b.name.indexOf("LayerTypeId") - a.name.indexOf("LayerTypeId"));
|
|
2301
|
-
for (const propertySymbol of propertiesSymbols) {
|
|
2302
|
-
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2303
|
-
const varianceArgs = yield* option(layerVarianceStruct(
|
|
2304
|
-
propertyType,
|
|
2305
|
-
atLocation
|
|
2306
|
-
));
|
|
2307
|
-
if (isSome2(varianceArgs)) {
|
|
2308
|
-
return varianceArgs.value;
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
return yield* typeParserIssue("Type has no layer variance struct", type, atLocation);
|
|
2312
|
-
});
|
|
2313
|
-
var fiberType = fn("TypeParser.fiberType")(function* (type, atLocation) {
|
|
2314
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2315
|
-
const awaitSymbol = typeChecker.getPropertyOfType(type, "await");
|
|
2316
|
-
const pollSymbol = typeChecker.getPropertyOfType(type, "poll");
|
|
2317
|
-
if (!awaitSymbol || !pollSymbol) {
|
|
2318
|
-
return yield* typeParserIssue(
|
|
2319
|
-
"Type is not a fiber because it does not have 'await' or 'poll' property",
|
|
2320
|
-
type,
|
|
2321
|
-
atLocation
|
|
2322
|
-
);
|
|
2323
|
-
}
|
|
2324
|
-
return yield* effectType(type, atLocation);
|
|
2325
|
-
});
|
|
2326
|
-
var effectSubtype = fn("TypeParser.effectSubtype")(function* (type, atLocation) {
|
|
2327
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2328
|
-
const tagSymbol = typeChecker.getPropertyOfType(type, "_tag");
|
|
2329
|
-
const getSymbol = typeChecker.getPropertyOfType(type, "get");
|
|
2330
|
-
if (!(tagSymbol || getSymbol)) {
|
|
2331
|
-
return yield* typeParserIssue(
|
|
2332
|
-
"Type is not a subtype of effect because it does not have '_tag' or 'get' property",
|
|
2333
|
-
type,
|
|
2334
|
-
atLocation
|
|
2335
|
-
);
|
|
2336
|
-
}
|
|
2337
|
-
return yield* effectType(type, atLocation);
|
|
2338
|
-
});
|
|
2339
|
-
var importedEffectModule = fn("TypeParser.importedEffectModule")(function* (node) {
|
|
2340
|
-
const ts = yield* service(TypeScriptApi);
|
|
2341
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2342
|
-
const type = typeChecker.getTypeAtLocation(node);
|
|
2343
|
-
const propertySymbol = typeChecker.getPropertyOfType(type, "never");
|
|
2344
|
-
if (!propertySymbol) {
|
|
2345
|
-
return yield* typeParserIssue("Type has no 'never' property", type, node);
|
|
2346
|
-
}
|
|
2347
|
-
if (!ts.isExpression(node)) {
|
|
2348
|
-
return yield* typeParserIssue("Node is not an expression", type, node);
|
|
2349
|
-
}
|
|
2350
|
-
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, node);
|
|
2351
|
-
yield* effectType(propertyType, node);
|
|
2352
|
-
return node;
|
|
2353
|
-
});
|
|
2354
|
-
var effectGen = fn("TypeParser.effectGen")(function* (node) {
|
|
2355
|
-
const ts = yield* service(TypeScriptApi);
|
|
2356
|
-
if (!ts.isCallExpression(node)) {
|
|
2357
|
-
return yield* typeParserIssue("Node is not a call expression", void 0, node);
|
|
2358
|
-
}
|
|
2359
|
-
if (node.arguments.length === 0) {
|
|
2360
|
-
return yield* typeParserIssue("Node has no arguments", void 0, node);
|
|
2361
|
-
}
|
|
2362
|
-
const generatorFunction = node.arguments[0];
|
|
2363
|
-
if (!ts.isFunctionExpression(generatorFunction)) {
|
|
2364
|
-
return yield* typeParserIssue("Node is not a function expression", void 0, node);
|
|
2365
|
-
}
|
|
2366
|
-
if (generatorFunction.asteriskToken === void 0) {
|
|
2367
|
-
return yield* typeParserIssue("Node is not a generator function", void 0, node);
|
|
2368
|
-
}
|
|
2369
|
-
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
2370
|
-
return yield* typeParserIssue("Node is not a property access expression", void 0, node);
|
|
2371
|
-
}
|
|
2372
|
-
const propertyAccess = node.expression;
|
|
2373
|
-
if (propertyAccess.name.text !== "gen") {
|
|
2374
|
-
return yield* typeParserIssue("Call expression name is not 'gen'", void 0, node);
|
|
2375
|
-
}
|
|
2376
|
-
const effectModule = yield* importedEffectModule(propertyAccess.expression);
|
|
2377
|
-
return {
|
|
2378
|
-
node,
|
|
2379
|
-
effectModule,
|
|
2380
|
-
generatorFunction,
|
|
2381
|
-
body: generatorFunction.body,
|
|
2382
|
-
functionStar: generatorFunction.getFirstToken()
|
|
2383
|
-
};
|
|
2384
|
-
});
|
|
2385
|
-
var effectFnUntracedGen = fn("TypeParser.effectFnUntracedGen")(
|
|
2386
|
-
function* (node) {
|
|
2387
|
-
const ts = yield* service(TypeScriptApi);
|
|
2388
|
-
if (!ts.isCallExpression(node)) {
|
|
2389
|
-
return yield* typeParserIssue("Node is not a call expression", void 0, node);
|
|
2390
|
-
}
|
|
2391
|
-
if (node.arguments.length === 0) {
|
|
2392
|
-
return yield* typeParserIssue("Node has no arguments", void 0, node);
|
|
2393
|
-
}
|
|
2394
|
-
const generatorFunction = node.arguments[0];
|
|
2395
|
-
if (!ts.isFunctionExpression(generatorFunction)) {
|
|
2396
|
-
return yield* typeParserIssue("Node is not a function expression", void 0, node);
|
|
2397
|
-
}
|
|
2398
|
-
if (generatorFunction.asteriskToken === void 0) {
|
|
2399
|
-
return yield* typeParserIssue(
|
|
2400
|
-
"Node is not a generator function",
|
|
2401
|
-
void 0,
|
|
2402
|
-
node
|
|
2403
|
-
);
|
|
2404
|
-
}
|
|
2405
|
-
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
2406
|
-
return yield* typeParserIssue(
|
|
2407
|
-
"Node is not a property access expression",
|
|
2408
|
-
void 0,
|
|
2409
|
-
node
|
|
2410
|
-
);
|
|
2411
|
-
}
|
|
2412
|
-
const propertyAccess = node.expression;
|
|
2413
|
-
if (propertyAccess.name.text !== "fnUntraced") {
|
|
2414
|
-
return yield* typeParserIssue(
|
|
2415
|
-
"Call expression name is not 'fnUntraced'",
|
|
2416
|
-
void 0,
|
|
2417
|
-
node
|
|
2418
|
-
);
|
|
2419
|
-
}
|
|
2420
|
-
const effectModule = yield* importedEffectModule(propertyAccess.expression);
|
|
2421
|
-
return {
|
|
2422
|
-
node,
|
|
2423
|
-
effectModule,
|
|
2424
|
-
generatorFunction,
|
|
2425
|
-
body: generatorFunction.body,
|
|
2426
|
-
functionStar: generatorFunction.getFirstToken()
|
|
2427
|
-
};
|
|
2428
|
-
}
|
|
2429
|
-
);
|
|
2430
|
-
var effectFnGen = fn("TypeParser.effectFnGen")(function* (node) {
|
|
2431
|
-
const ts = yield* service(TypeScriptApi);
|
|
2432
|
-
if (!ts.isCallExpression(node)) {
|
|
2433
|
-
return yield* typeParserIssue("Node is not a call expression", void 0, node);
|
|
2434
|
-
}
|
|
2435
|
-
if (node.arguments.length === 0) {
|
|
2436
|
-
return yield* typeParserIssue("Node has no arguments", void 0, node);
|
|
2437
|
-
}
|
|
2438
|
-
const generatorFunction = node.arguments[0];
|
|
2439
|
-
if (!ts.isFunctionExpression(generatorFunction)) {
|
|
2440
|
-
return yield* typeParserIssue(
|
|
2441
|
-
"Node is not a function expression",
|
|
2442
|
-
void 0,
|
|
2443
|
-
node
|
|
2444
|
-
);
|
|
2445
|
-
}
|
|
2446
|
-
if (generatorFunction.asteriskToken === void 0) {
|
|
2447
|
-
return yield* typeParserIssue(
|
|
2448
|
-
"Node is not a generator function",
|
|
2449
|
-
void 0,
|
|
2450
|
-
node
|
|
2451
|
-
);
|
|
2452
|
-
}
|
|
2453
|
-
const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
|
|
2454
|
-
if (!ts.isPropertyAccessExpression(expressionToTest)) {
|
|
2455
|
-
return yield* typeParserIssue(
|
|
2456
|
-
"Node is not a property access expression",
|
|
2457
|
-
void 0,
|
|
2458
|
-
node
|
|
2459
|
-
);
|
|
2460
|
-
}
|
|
2461
|
-
const propertyAccess = expressionToTest;
|
|
2462
|
-
if (propertyAccess.name.text !== "fn") {
|
|
2463
|
-
return yield* typeParserIssue(
|
|
2464
|
-
"Call expression name is not 'fn'",
|
|
2465
|
-
void 0,
|
|
2466
|
-
node
|
|
2467
|
-
);
|
|
2468
|
-
}
|
|
2469
|
-
const effectModule = yield* importedEffectModule(propertyAccess.expression);
|
|
2470
|
-
return {
|
|
2471
|
-
node,
|
|
2472
|
-
generatorFunction,
|
|
2473
|
-
effectModule,
|
|
2474
|
-
body: generatorFunction.body,
|
|
2475
|
-
functionStar: generatorFunction.getFirstToken()
|
|
2476
|
-
};
|
|
2477
|
-
});
|
|
2478
|
-
var unnecessaryEffectGen = fn("TypeParser.unnecessaryEffectGen")(function* (node) {
|
|
2479
|
-
const ts = yield* service(TypeScriptApi);
|
|
2480
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2481
|
-
const { body } = yield* effectGen(node);
|
|
2482
|
-
if (body.statements.length !== 1) {
|
|
2483
|
-
return yield* typeParserIssue(
|
|
2484
|
-
"Generator body should have a single statement",
|
|
2485
|
-
void 0,
|
|
2486
|
-
node
|
|
2487
|
-
);
|
|
2488
|
-
}
|
|
2489
|
-
let explicitReturn = false;
|
|
2490
|
-
let nodeToCheck = body.statements[0];
|
|
2491
|
-
while (nodeToCheck) {
|
|
2492
|
-
if (ts.isReturnStatement(nodeToCheck) && nodeToCheck.expression) {
|
|
2493
|
-
nodeToCheck = nodeToCheck.expression;
|
|
2494
|
-
explicitReturn = true;
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
2495
2632
|
continue;
|
|
2496
|
-
}
|
|
2497
|
-
|
|
2498
|
-
|
|
2633
|
+
} else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
2634
|
+
const expectedType = typeChecker.getTypeAtLocation(node.left);
|
|
2635
|
+
const realType = typeChecker.getTypeAtLocation(node.right);
|
|
2636
|
+
result.push([node.left, expectedType, node.right, realType]);
|
|
2637
|
+
appendNodeToVisit(node.right);
|
|
2499
2638
|
continue;
|
|
2500
|
-
}
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
]
|
|
2527
|
-
);
|
|
2528
|
-
}),
|
|
2529
|
-
provideService(TypeScriptApi, ts)
|
|
2530
|
-
);
|
|
2639
|
+
} else if (ts.isReturnStatement(node) && node.expression) {
|
|
2640
|
+
const parentDeclaration = yield* option(getAncestorConvertibleDeclaration(node));
|
|
2641
|
+
if (isSome2(parentDeclaration)) {
|
|
2642
|
+
const expectedType = yield* option(getInferredReturnType(parentDeclaration.value));
|
|
2643
|
+
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2644
|
+
if (isSome2(expectedType)) {
|
|
2645
|
+
result.push([node, expectedType.value, node, realType]);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
2649
|
+
continue;
|
|
2650
|
+
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length === 0 && ts.isExpression(node.body)) {
|
|
2651
|
+
const body = node.body;
|
|
2652
|
+
const expectedType = typeChecker.getContextualType(body);
|
|
2653
|
+
const realType = typeChecker.getTypeAtLocation(body);
|
|
2654
|
+
if (expectedType) {
|
|
2655
|
+
result.push([body, expectedType, body, realType]);
|
|
2656
|
+
}
|
|
2657
|
+
ts.forEachChild(body, appendNodeToVisit);
|
|
2658
|
+
continue;
|
|
2659
|
+
} else if (ts.isArrowFunction(node) && (node.typeParameters || []).length > 0 && ts.isExpression(node.body)) {
|
|
2660
|
+
const body = node.body;
|
|
2661
|
+
const expectedType = yield* option(getInferredReturnType(node));
|
|
2662
|
+
const realType = typeChecker.getTypeAtLocation(body);
|
|
2663
|
+
if (isSome2(expectedType)) {
|
|
2664
|
+
result.push([body, expectedType.value, body, realType]);
|
|
2531
2665
|
}
|
|
2532
|
-
|
|
2666
|
+
ts.forEachChild(body, appendNodeToVisit);
|
|
2667
|
+
continue;
|
|
2668
|
+
} else if (ts.isSatisfiesExpression(node)) {
|
|
2669
|
+
const expectedType = typeChecker.getTypeAtLocation(node.type);
|
|
2670
|
+
const realType = typeChecker.getTypeAtLocation(node.expression);
|
|
2671
|
+
result.push([node.expression, expectedType, node.expression, realType]);
|
|
2672
|
+
appendNodeToVisit(node.expression);
|
|
2673
|
+
continue;
|
|
2533
2674
|
}
|
|
2534
|
-
|
|
2675
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
2535
2676
|
}
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
void 0,
|
|
2539
|
-
node
|
|
2540
|
-
);
|
|
2677
|
+
cache.expectedAndRealType.set(sourceFile, result);
|
|
2678
|
+
return result;
|
|
2541
2679
|
});
|
|
2542
|
-
var
|
|
2543
|
-
|
|
2680
|
+
var appendToUniqueTypesMap = fn(
|
|
2681
|
+
"TypeCheckerApi.appendToUniqueTypesMap"
|
|
2682
|
+
)(
|
|
2683
|
+
function* (memory, initialType, excludeNever) {
|
|
2684
|
+
const ts = yield* service(TypeScriptApi);
|
|
2685
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2686
|
+
const newIndexes = /* @__PURE__ */ new Set();
|
|
2687
|
+
const knownIndexes = /* @__PURE__ */ new Set();
|
|
2688
|
+
let toTest = [initialType];
|
|
2689
|
+
while (toTest.length > 0) {
|
|
2690
|
+
const type = toTest.pop();
|
|
2691
|
+
if (!type) break;
|
|
2692
|
+
if (excludeNever && type.flags & ts.TypeFlags.Never) {
|
|
2693
|
+
continue;
|
|
2694
|
+
}
|
|
2695
|
+
if (type.isUnion()) {
|
|
2696
|
+
toTest = toTest.concat(type.types);
|
|
2697
|
+
} else {
|
|
2698
|
+
const foundMatch = [];
|
|
2699
|
+
for (const [typeId, knownType] of memory.entries()) {
|
|
2700
|
+
const areSame = typeChecker.isTypeAssignableTo(knownType, type) && typeChecker.isTypeAssignableTo(type, knownType);
|
|
2701
|
+
if (areSame) {
|
|
2702
|
+
foundMatch.push(typeId);
|
|
2703
|
+
break;
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
if (foundMatch.length === 0) {
|
|
2707
|
+
const newId = "t" + (memory.size + 1);
|
|
2708
|
+
memory.set(newId, type);
|
|
2709
|
+
newIndexes.add(newId);
|
|
2710
|
+
} else {
|
|
2711
|
+
knownIndexes.add(foundMatch[0]);
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2544
2715
|
return {
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2716
|
+
newIndexes,
|
|
2717
|
+
knownIndexes,
|
|
2718
|
+
allIndexes: pipe(
|
|
2719
|
+
fromIterable(newIndexes),
|
|
2720
|
+
appendAll(fromIterable(knownIndexes))
|
|
2721
|
+
)
|
|
2548
2722
|
};
|
|
2549
2723
|
}
|
|
2550
2724
|
);
|
|
2551
|
-
var effectSchemaType = fn("TypeParser.effectSchemaType")(function* (type, atLocation) {
|
|
2552
|
-
const ts = yield* service(TypeScriptApi);
|
|
2553
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
2554
|
-
yield* pipeableType(type, atLocation);
|
|
2555
|
-
const ast = typeChecker.getPropertyOfType(type, "ast");
|
|
2556
|
-
if (!ast) return yield* typeParserIssue("Has no 'ast' property", type, atLocation);
|
|
2557
|
-
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
2558
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
|
|
2559
|
-
);
|
|
2560
|
-
propertiesSymbols.sort((a, b) => b.name.indexOf("TypeId") - a.name.indexOf("TypeId"));
|
|
2561
|
-
for (const propertySymbol of propertiesSymbols) {
|
|
2562
|
-
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
2563
|
-
const varianceArgs = yield* option(effectSchemaVarianceStruct(
|
|
2564
|
-
propertyType,
|
|
2565
|
-
atLocation
|
|
2566
|
-
));
|
|
2567
|
-
if (isSome2(varianceArgs)) {
|
|
2568
|
-
return varianceArgs.value;
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
return yield* typeParserIssue("Type has no schema variance struct", type, atLocation);
|
|
2572
|
-
});
|
|
2573
|
-
|
|
2574
|
-
// src/completions/fnFunctionStar.ts
|
|
2575
|
-
var fnFunctionStar = createCompletion({
|
|
2576
|
-
name: "fnFunctionStar",
|
|
2577
|
-
apply: fn("fnFunctionStar")(function* (sourceFile, position) {
|
|
2578
|
-
const ts = yield* service(TypeScriptApi);
|
|
2579
|
-
const maybeInfos = yield* option(
|
|
2580
|
-
parseAccessedExpressionForCompletion(sourceFile, position)
|
|
2581
|
-
);
|
|
2582
|
-
if (isNone2(maybeInfos)) return [];
|
|
2583
|
-
const { accessedObject } = maybeInfos.value;
|
|
2584
|
-
const isEffectModule = yield* option(importedEffectModule(accessedObject));
|
|
2585
|
-
if (isNone2(isEffectModule)) return [];
|
|
2586
|
-
const span = ts.createTextSpan(
|
|
2587
|
-
accessedObject.end + 1,
|
|
2588
|
-
Math.max(0, position - accessedObject.end - 1)
|
|
2589
|
-
);
|
|
2590
|
-
const maybeFnName = pipe(
|
|
2591
|
-
yield* getAncestorNodesInRange(sourceFile, toTextRange(accessedObject.pos)),
|
|
2592
|
-
filter(ts.isVariableDeclaration),
|
|
2593
|
-
map3((_) => _.name && ts.isIdentifier(_.name) ? _.name.text : ""),
|
|
2594
|
-
filter((_) => _.length > 0),
|
|
2595
|
-
head,
|
|
2596
|
-
map2((name) => [
|
|
2597
|
-
{
|
|
2598
|
-
name: `fn("${name}")`,
|
|
2599
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2600
|
-
insertText: `fn("${name}")(function*(${"${1}"}){${"${0}"}})`,
|
|
2601
|
-
replacementSpan: span,
|
|
2602
|
-
isSnippet: true
|
|
2603
|
-
}
|
|
2604
|
-
]),
|
|
2605
|
-
getOrElse2(() => [])
|
|
2606
|
-
);
|
|
2607
|
-
return maybeFnName.concat([{
|
|
2608
|
-
name: `fn(function*(){})`,
|
|
2609
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2610
|
-
insertText: `fn(function*(${"${1}"}){${"${0}"}})`,
|
|
2611
|
-
replacementSpan: span,
|
|
2612
|
-
isSnippet: true
|
|
2613
|
-
}, {
|
|
2614
|
-
name: `fnUntraced(function*(){})`,
|
|
2615
|
-
kind: ts.ScriptElementKind.constElement,
|
|
2616
|
-
insertText: `fnUntraced(function*(${"${1}"}){${"${0}"}})`,
|
|
2617
|
-
replacementSpan: span,
|
|
2618
|
-
isSnippet: true
|
|
2619
|
-
}]);
|
|
2620
|
-
})
|
|
2621
|
-
});
|
|
2622
2725
|
|
|
2623
2726
|
// src/completions/genFunctionStar.ts
|
|
2624
2727
|
var genFunctionStar = createCompletion({
|
|
@@ -2701,6 +2804,7 @@ function parse(config) {
|
|
|
2701
2804
|
diagnostics: isObject(config) && hasProperty(config, "diagnostics") && isBoolean(config.diagnostics) ? config.diagnostics : true,
|
|
2702
2805
|
quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : true,
|
|
2703
2806
|
completions: isObject(config) && hasProperty(config, "completions") && isBoolean(config.completions) ? config.completions : true,
|
|
2807
|
+
goto: isObject(config) && hasProperty(config, "goto") && isBoolean(config.goto) ? config.goto : true,
|
|
2704
2808
|
allowedDuplicatedPackages: isObject(config) && hasProperty(config, "allowedDuplicatedPackages") && isArray(config.allowedDuplicatedPackages) && config.allowedDuplicatedPackages.every(isString) ? config.allowedDuplicatedPackages.map((_) => _.toLowerCase()) : []
|
|
2705
2809
|
};
|
|
2706
2810
|
}
|
|
@@ -2761,6 +2865,7 @@ var floatingEffect = createDiagnostic({
|
|
|
2761
2865
|
apply: fn("floatingEffect.apply")(function* (sourceFile) {
|
|
2762
2866
|
const ts = yield* service(TypeScriptApi);
|
|
2763
2867
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2868
|
+
const typeParser = yield* service(TypeParser);
|
|
2764
2869
|
function isFloatingExpression(node) {
|
|
2765
2870
|
if (!ts.isExpressionStatement(node)) return false;
|
|
2766
2871
|
if (!(ts.isBlock(node.parent) || ts.isSourceFile(node.parent))) return false;
|
|
@@ -2780,11 +2885,11 @@ var floatingEffect = createDiagnostic({
|
|
|
2780
2885
|
ts.forEachChild(node, appendNodeToVisit);
|
|
2781
2886
|
if (!isFloatingExpression(node)) continue;
|
|
2782
2887
|
const type = typeChecker.getTypeAtLocation(node.expression);
|
|
2783
|
-
const effect = yield* option(effectType(type, node.expression));
|
|
2888
|
+
const effect = yield* option(typeParser.effectType(type, node.expression));
|
|
2784
2889
|
if (isSome2(effect)) {
|
|
2785
2890
|
const allowedFloatingEffects = yield* pipe(
|
|
2786
|
-
fiberType(type, node.expression),
|
|
2787
|
-
orElse3(() => effectSubtype(type, node.expression)),
|
|
2891
|
+
typeParser.fiberType(type, node.expression),
|
|
2892
|
+
orElse3(() => typeParser.effectSubtype(type, node.expression)),
|
|
2788
2893
|
option
|
|
2789
2894
|
);
|
|
2790
2895
|
if (isNone2(allowedFloatingEffects)) {
|
|
@@ -2801,6 +2906,112 @@ var floatingEffect = createDiagnostic({
|
|
|
2801
2906
|
})
|
|
2802
2907
|
});
|
|
2803
2908
|
|
|
2909
|
+
// src/diagnostics/leakingRequirements.ts
|
|
2910
|
+
var leakingRequirements = createDiagnostic({
|
|
2911
|
+
name: "leakingRequirements",
|
|
2912
|
+
code: 8,
|
|
2913
|
+
apply: fn("leakingRequirements.apply")(function* (sourceFile) {
|
|
2914
|
+
const ts = yield* service(TypeScriptApi);
|
|
2915
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2916
|
+
const typeParser = yield* service(TypeParser);
|
|
2917
|
+
const typeOrder = yield* deterministicTypeOrder;
|
|
2918
|
+
const effectDiagnostics = [];
|
|
2919
|
+
const parseLeakedRequirements = cachedBy(
|
|
2920
|
+
fn("leakingServices.checkServiceLeaking")(
|
|
2921
|
+
function* (service2, atLocation) {
|
|
2922
|
+
const properties = typeChecker.getPropertiesOfType(service2);
|
|
2923
|
+
if (properties.length < 1) return [];
|
|
2924
|
+
const memory = /* @__PURE__ */ new Map();
|
|
2925
|
+
let sharedRequirementsKeys = void 0;
|
|
2926
|
+
let effectMembers = 0;
|
|
2927
|
+
for (const property of properties) {
|
|
2928
|
+
const servicePropertyType = typeChecker.getTypeOfSymbolAtLocation(property, atLocation);
|
|
2929
|
+
let effectContextType = void 0;
|
|
2930
|
+
yield* pipe(
|
|
2931
|
+
typeParser.effectType(servicePropertyType, atLocation),
|
|
2932
|
+
map4((_) => effectContextType = _.R),
|
|
2933
|
+
orElse3(() => {
|
|
2934
|
+
const servicePropertyCallSignatures = servicePropertyType.getCallSignatures();
|
|
2935
|
+
if (servicePropertyCallSignatures.length === 1) {
|
|
2936
|
+
return pipe(
|
|
2937
|
+
typeParser.effectType(servicePropertyCallSignatures[0].getReturnType(), atLocation),
|
|
2938
|
+
map4((_) => {
|
|
2939
|
+
effectContextType = _.R;
|
|
2940
|
+
})
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
return void_2;
|
|
2944
|
+
}),
|
|
2945
|
+
ignore
|
|
2946
|
+
);
|
|
2947
|
+
if (effectContextType) {
|
|
2948
|
+
effectMembers++;
|
|
2949
|
+
const { allIndexes } = yield* appendToUniqueTypesMap(memory, effectContextType, true);
|
|
2950
|
+
if (!sharedRequirementsKeys) {
|
|
2951
|
+
sharedRequirementsKeys = allIndexes;
|
|
2952
|
+
} else {
|
|
2953
|
+
sharedRequirementsKeys = intersection(sharedRequirementsKeys, allIndexes);
|
|
2954
|
+
if (sharedRequirementsKeys.length === 0) return [];
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
if (sharedRequirementsKeys && sharedRequirementsKeys.length > 0 && effectMembers >= 2) {
|
|
2959
|
+
return sharedRequirementsKeys.map((key) => memory.get(key));
|
|
2960
|
+
}
|
|
2961
|
+
return [];
|
|
2962
|
+
}
|
|
2963
|
+
),
|
|
2964
|
+
"leakingServices.checkServiceLeaking",
|
|
2965
|
+
(_, service2) => service2
|
|
2966
|
+
);
|
|
2967
|
+
function reportLeakingRequirements(node, requirements) {
|
|
2968
|
+
if (requirements.length === 0) return;
|
|
2969
|
+
effectDiagnostics.push({
|
|
2970
|
+
node,
|
|
2971
|
+
category: ts.DiagnosticCategory.Warning,
|
|
2972
|
+
messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement`,
|
|
2973
|
+
fixes: []
|
|
2974
|
+
});
|
|
2975
|
+
}
|
|
2976
|
+
const nodeToVisit = [];
|
|
2977
|
+
const appendNodeToVisit = (node) => {
|
|
2978
|
+
nodeToVisit.push(node);
|
|
2979
|
+
return void 0;
|
|
2980
|
+
};
|
|
2981
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
2982
|
+
while (nodeToVisit.length > 0) {
|
|
2983
|
+
const node = nodeToVisit.shift();
|
|
2984
|
+
const typesToCheck = [];
|
|
2985
|
+
if (ts.isCallExpression(node)) {
|
|
2986
|
+
typesToCheck.push([typeChecker.getTypeAtLocation(node), node]);
|
|
2987
|
+
} else if (ts.isClassDeclaration(node) && node.name) {
|
|
2988
|
+
const classSym = typeChecker.getSymbolAtLocation(node.name);
|
|
2989
|
+
if (classSym) {
|
|
2990
|
+
const type = typeChecker.getTypeOfSymbol(classSym);
|
|
2991
|
+
typesToCheck.push([type, node.name]);
|
|
2992
|
+
}
|
|
2993
|
+
} else {
|
|
2994
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
2995
|
+
continue;
|
|
2996
|
+
}
|
|
2997
|
+
for (const [type, reportAt] of typesToCheck) {
|
|
2998
|
+
yield* pipe(
|
|
2999
|
+
typeParser.contextTag(type, node),
|
|
3000
|
+
flatMap3(
|
|
3001
|
+
({ Service }) => pipe(
|
|
3002
|
+
parseLeakedRequirements(Service, node),
|
|
3003
|
+
map4((requirements) => reportLeakingRequirements(reportAt, sort(requirements, typeOrder)))
|
|
3004
|
+
)
|
|
3005
|
+
),
|
|
3006
|
+
orElse3(() => sync(() => ts.forEachChild(node, appendNodeToVisit))),
|
|
3007
|
+
ignore
|
|
3008
|
+
);
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
return effectDiagnostics;
|
|
3012
|
+
})
|
|
3013
|
+
});
|
|
3014
|
+
|
|
2804
3015
|
// src/diagnostics/missingEffectContext.ts
|
|
2805
3016
|
var missingEffectContext = createDiagnostic({
|
|
2806
3017
|
name: "missingEffectContext",
|
|
@@ -2808,15 +3019,16 @@ var missingEffectContext = createDiagnostic({
|
|
|
2808
3019
|
apply: fn("missingEffectContext.apply")(function* (sourceFile) {
|
|
2809
3020
|
const ts = yield* service(TypeScriptApi);
|
|
2810
3021
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3022
|
+
const typeParser = yield* service(TypeParser);
|
|
2811
3023
|
const typeOrder = yield* deterministicTypeOrder;
|
|
2812
3024
|
const checkForMissingContextTypes = fn(
|
|
2813
3025
|
"missingEffectContext.apply.checkForMissingContextTypes"
|
|
2814
3026
|
)(function* (node, expectedType, valueNode, realType) {
|
|
2815
|
-
const expectedEffect = yield* effectType(
|
|
3027
|
+
const expectedEffect = yield* typeParser.effectType(
|
|
2816
3028
|
expectedType,
|
|
2817
3029
|
node
|
|
2818
3030
|
);
|
|
2819
|
-
const realEffect = yield* effectType(
|
|
3031
|
+
const realEffect = yield* typeParser.effectType(
|
|
2820
3032
|
realType,
|
|
2821
3033
|
valueNode
|
|
2822
3034
|
);
|
|
@@ -2860,14 +3072,15 @@ var missingEffectError = createDiagnostic({
|
|
|
2860
3072
|
apply: fn("missingEffectError.apply")(function* (sourceFile) {
|
|
2861
3073
|
const ts = yield* service(TypeScriptApi);
|
|
2862
3074
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3075
|
+
const typeParser = yield* service(TypeParser);
|
|
2863
3076
|
const typeOrder = yield* deterministicTypeOrder;
|
|
2864
3077
|
const checkForMissingErrorTypes = fn("missingEffectError.apply.checkForMissingErrorTypes")(
|
|
2865
3078
|
function* (node, expectedType, valueNode, realType) {
|
|
2866
|
-
const expectedEffect = yield* effectType(
|
|
3079
|
+
const expectedEffect = yield* typeParser.effectType(
|
|
2867
3080
|
expectedType,
|
|
2868
3081
|
node
|
|
2869
3082
|
);
|
|
2870
|
-
const realEffect = yield* effectType(
|
|
3083
|
+
const realEffect = yield* typeParser.effectType(
|
|
2871
3084
|
realType,
|
|
2872
3085
|
valueNode
|
|
2873
3086
|
);
|
|
@@ -2912,6 +3125,7 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
2912
3125
|
apply: fn("missingReturnYieldStar.apply")(function* (sourceFile) {
|
|
2913
3126
|
const ts = yield* service(TypeScriptApi);
|
|
2914
3127
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3128
|
+
const typeParser = yield* service(TypeParser);
|
|
2915
3129
|
const effectDiagnostics = [];
|
|
2916
3130
|
const brokenYields = /* @__PURE__ */ new Set();
|
|
2917
3131
|
const nodeToVisit = [];
|
|
@@ -2925,7 +3139,7 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
2925
3139
|
ts.forEachChild(node, appendNodeToVisit);
|
|
2926
3140
|
if (ts.isYieldExpression(node) && node.expression && node.asteriskToken) {
|
|
2927
3141
|
const type = typeChecker.getTypeAtLocation(node.expression);
|
|
2928
|
-
const maybeEffect = yield* option(effectType(type, node.expression));
|
|
3142
|
+
const maybeEffect = yield* option(typeParser.effectType(type, node.expression));
|
|
2929
3143
|
if (isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never) {
|
|
2930
3144
|
const generatorFunctionOrReturnStatement = ts.findAncestor(
|
|
2931
3145
|
node,
|
|
@@ -2935,9 +3149,9 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
2935
3149
|
if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.parent) {
|
|
2936
3150
|
const effectGenNode = generatorFunctionOrReturnStatement.parent;
|
|
2937
3151
|
const effectGenLike = yield* pipe(
|
|
2938
|
-
effectGen(effectGenNode),
|
|
2939
|
-
orElse3(() => effectFnUntracedGen(effectGenNode)),
|
|
2940
|
-
orElse3(() => effectFnGen(effectGenNode)),
|
|
3152
|
+
typeParser.effectGen(effectGenNode),
|
|
3153
|
+
orElse3(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3154
|
+
orElse3(() => typeParser.effectFnGen(effectGenNode)),
|
|
2941
3155
|
option
|
|
2942
3156
|
);
|
|
2943
3157
|
if (isSome2(effectGenLike)) {
|
|
@@ -2980,6 +3194,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
2980
3194
|
code: 4,
|
|
2981
3195
|
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile) {
|
|
2982
3196
|
const ts = yield* service(TypeScriptApi);
|
|
3197
|
+
const typeParser = yield* service(TypeParser);
|
|
2983
3198
|
const effectDiagnostics = [];
|
|
2984
3199
|
const brokenGenerators = /* @__PURE__ */ new Set();
|
|
2985
3200
|
const brokenYields = /* @__PURE__ */ new Set();
|
|
@@ -2999,18 +3214,18 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
2999
3214
|
);
|
|
3000
3215
|
if (functionStarNode && functionStarNode.parent) {
|
|
3001
3216
|
const effectGenNode = functionStarNode.parent;
|
|
3002
|
-
|
|
3003
|
-
effectGen(effectGenNode),
|
|
3004
|
-
orElse3(() => effectFnUntracedGen(effectGenNode)),
|
|
3005
|
-
orElse3(() => effectFnGen(effectGenNode)),
|
|
3006
|
-
|
|
3217
|
+
yield* pipe(
|
|
3218
|
+
typeParser.effectGen(effectGenNode),
|
|
3219
|
+
orElse3(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3220
|
+
orElse3(() => typeParser.effectFnGen(effectGenNode)),
|
|
3221
|
+
map4(({ functionStar }) => {
|
|
3222
|
+
if (functionStar) {
|
|
3223
|
+
brokenGenerators.add(functionStar);
|
|
3224
|
+
}
|
|
3225
|
+
brokenYields.add(node);
|
|
3226
|
+
}),
|
|
3227
|
+
ignore
|
|
3007
3228
|
);
|
|
3008
|
-
if (isSome2(effectGenLike)) {
|
|
3009
|
-
if (effectGenLike.value.functionStar) {
|
|
3010
|
-
brokenGenerators.add(effectGenLike.value.functionStar);
|
|
3011
|
-
}
|
|
3012
|
-
brokenYields.add(node);
|
|
3013
|
-
}
|
|
3014
3229
|
}
|
|
3015
3230
|
}
|
|
3016
3231
|
}
|
|
@@ -3050,11 +3265,12 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
3050
3265
|
});
|
|
3051
3266
|
|
|
3052
3267
|
// src/diagnostics/unnecessaryEffectGen.ts
|
|
3053
|
-
var
|
|
3268
|
+
var unnecessaryEffectGen = createDiagnostic({
|
|
3054
3269
|
name: "unnecessaryEffectGen",
|
|
3055
3270
|
code: 5,
|
|
3056
3271
|
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile) {
|
|
3057
3272
|
const ts = yield* service(TypeScriptApi);
|
|
3273
|
+
const typeParser = yield* service(TypeParser);
|
|
3058
3274
|
const effectDiagnostics = [];
|
|
3059
3275
|
const unnecessaryGenerators = /* @__PURE__ */ new Map();
|
|
3060
3276
|
const nodeToVisit = [];
|
|
@@ -3066,9 +3282,12 @@ var unnecessaryEffectGen2 = createDiagnostic({
|
|
|
3066
3282
|
while (nodeToVisit.length > 0) {
|
|
3067
3283
|
const node = nodeToVisit.shift();
|
|
3068
3284
|
ts.forEachChild(node, appendNodeToVisit);
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3285
|
+
if (ts.isCallExpression(node)) {
|
|
3286
|
+
yield* pipe(
|
|
3287
|
+
typeParser.unnecessaryEffectGen(node),
|
|
3288
|
+
map4(({ replacementNode }) => unnecessaryGenerators.set(node, replacementNode)),
|
|
3289
|
+
ignore
|
|
3290
|
+
);
|
|
3072
3291
|
}
|
|
3073
3292
|
}
|
|
3074
3293
|
unnecessaryGenerators.forEach(
|
|
@@ -3099,8 +3318,9 @@ var diagnostics = [
|
|
|
3099
3318
|
missingEffectError,
|
|
3100
3319
|
floatingEffect,
|
|
3101
3320
|
missingStarInYieldEffectGen,
|
|
3102
|
-
|
|
3103
|
-
missingReturnYieldStar
|
|
3321
|
+
unnecessaryEffectGen,
|
|
3322
|
+
missingReturnYieldStar,
|
|
3323
|
+
leakingRequirements
|
|
3104
3324
|
];
|
|
3105
3325
|
|
|
3106
3326
|
// src/goto/effectRpcDefinition.ts
|
|
@@ -3242,6 +3462,7 @@ function effectTypeArgs(sourceFile, position, quickInfo2) {
|
|
|
3242
3462
|
gen2(function* () {
|
|
3243
3463
|
const ts = yield* service(TypeScriptApi);
|
|
3244
3464
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3465
|
+
const typeParser = yield* service(TypeParser);
|
|
3245
3466
|
const maybeNode = pipe(
|
|
3246
3467
|
yield* getAncestorNodesInRange(sourceFile, toTextRange(position)),
|
|
3247
3468
|
head
|
|
@@ -3251,13 +3472,13 @@ function effectTypeArgs(sourceFile, position, quickInfo2) {
|
|
|
3251
3472
|
const hasTruncationHappened = quickInfo2 && ts.displayPartsToString(quickInfo2.displayParts).indexOf("...") > -1;
|
|
3252
3473
|
const nodeForType = !quickInfo2 && ts.isYieldExpression(node) && node.asteriskToken && node.expression ? node.expression : hasTruncationHappened ? node : void 0;
|
|
3253
3474
|
if (!nodeForType) return quickInfo2;
|
|
3254
|
-
const
|
|
3475
|
+
const effectType = yield* typeParser.effectType(
|
|
3255
3476
|
typeChecker.getTypeAtLocation(nodeForType),
|
|
3256
3477
|
nodeForType
|
|
3257
3478
|
);
|
|
3258
3479
|
const effectTypeArgsDocumentation = [{
|
|
3259
3480
|
kind: "text",
|
|
3260
|
-
text: "```ts\n/* Effect Type Parameters */\n" + (yield* formatTypeForQuickInfo(
|
|
3481
|
+
text: "```ts\n/* Effect Type Parameters */\n" + (yield* formatTypeForQuickInfo(effectType.A, "Success")) + "\n" + (yield* formatTypeForQuickInfo(effectType.E, "Failure")) + "\n" + (yield* formatTypeForQuickInfo(effectType.R, "Requirements")) + "\n```\n"
|
|
3261
3482
|
}];
|
|
3262
3483
|
if (!quickInfo2) {
|
|
3263
3484
|
const start = node.getStart();
|
|
@@ -3315,6 +3536,7 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
|
|
|
3315
3536
|
return gen2(function* () {
|
|
3316
3537
|
const ts = yield* service(TypeScriptApi);
|
|
3317
3538
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3539
|
+
const typeParser = yield* service(TypeParser);
|
|
3318
3540
|
const maybePipe = yield* option(parsePipeCall(node));
|
|
3319
3541
|
if (isSome2(maybePipe)) {
|
|
3320
3542
|
let graphNode = yield* processLayerGraphNode(ctx, maybePipe.value.subject, void 0);
|
|
@@ -3325,7 +3547,7 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
|
|
|
3325
3547
|
}
|
|
3326
3548
|
if (ts.isCallExpression(node)) {
|
|
3327
3549
|
const type = typeChecker.getTypeAtLocation(node);
|
|
3328
|
-
const maybeLayer = yield* option(layerType(type, node));
|
|
3550
|
+
const maybeLayer = yield* option(typeParser.layerType(type, node));
|
|
3329
3551
|
if (isSome2(maybeLayer)) {
|
|
3330
3552
|
const argNodes = yield* option(
|
|
3331
3553
|
all2(...node.arguments.map((_) => processLayerGraphNode(ctx, _, void 0)))
|
|
@@ -3358,7 +3580,7 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
|
|
|
3358
3580
|
if (callSignatures.length === 1) {
|
|
3359
3581
|
const [signature] = callSignatures;
|
|
3360
3582
|
const returnType = signature.getReturnType();
|
|
3361
|
-
const maybeLayer = yield* option(layerType(returnType, node));
|
|
3583
|
+
const maybeLayer = yield* option(typeParser.layerType(returnType, node));
|
|
3362
3584
|
if (isSome2(maybeLayer)) {
|
|
3363
3585
|
const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
|
|
3364
3586
|
ctx.services,
|
|
@@ -3408,7 +3630,7 @@ function processLayerGraphNode(ctx, node, pipedInGraphNode) {
|
|
|
3408
3630
|
}
|
|
3409
3631
|
if (ts.isExpression(node)) {
|
|
3410
3632
|
const type = typeChecker.getTypeAtLocation(node);
|
|
3411
|
-
const maybeLayer = yield* option(layerType(type, node));
|
|
3633
|
+
const maybeLayer = yield* option(typeParser.layerType(type, node));
|
|
3412
3634
|
if (isSome2(maybeLayer)) {
|
|
3413
3635
|
const { allIndexes: outTypes } = yield* appendToUniqueTypesMap(
|
|
3414
3636
|
ctx.services,
|
|
@@ -3547,6 +3769,7 @@ function layerInfo(sourceFile, position, quickInfo2) {
|
|
|
3547
3769
|
gen2(function* () {
|
|
3548
3770
|
const ts = yield* service(TypeScriptApi);
|
|
3549
3771
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3772
|
+
const typeParser = yield* service(TypeParser);
|
|
3550
3773
|
const range = toTextRange(position);
|
|
3551
3774
|
const maybeNode = pipe(
|
|
3552
3775
|
yield* getAncestorNodesInRange(sourceFile, range),
|
|
@@ -3557,8 +3780,8 @@ function layerInfo(sourceFile, position, quickInfo2) {
|
|
|
3557
3780
|
if (isNone2(maybeNode)) return quickInfo2;
|
|
3558
3781
|
const node = maybeNode.value;
|
|
3559
3782
|
const layerNode = node.initializer ? node.initializer : node;
|
|
3560
|
-
const
|
|
3561
|
-
const maybeLayer = yield* option(layerType(
|
|
3783
|
+
const layerType = typeChecker.getTypeAtLocation(layerNode);
|
|
3784
|
+
const maybeLayer = yield* option(typeParser.layerType(layerType, layerNode));
|
|
3562
3785
|
if (isNone2(maybeLayer)) return quickInfo2;
|
|
3563
3786
|
let lastId = 0;
|
|
3564
3787
|
const graphCtx = {
|
|
@@ -3662,6 +3885,7 @@ var asyncAwaitToGen = createRefactor({
|
|
|
3662
3885
|
apply: fn("asyncAwaitToGen.apply")(function* (sourceFile, textRange) {
|
|
3663
3886
|
const ts = yield* service(TypeScriptApi);
|
|
3664
3887
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3888
|
+
const typeParser = yield* service(TypeParser);
|
|
3665
3889
|
const maybeNode = pipe(
|
|
3666
3890
|
yield* getAncestorNodesInRange(sourceFile, textRange),
|
|
3667
3891
|
filter(
|
|
@@ -3684,7 +3908,7 @@ var asyncAwaitToGen = createRefactor({
|
|
|
3684
3908
|
findImportedModuleIdentifier(
|
|
3685
3909
|
sourceFile,
|
|
3686
3910
|
(node2) => pipe(
|
|
3687
|
-
importedEffectModule(node2),
|
|
3911
|
+
typeParser.importedEffectModule(node2),
|
|
3688
3912
|
option,
|
|
3689
3913
|
map4(isSome2)
|
|
3690
3914
|
)
|
|
@@ -3732,6 +3956,7 @@ var asyncAwaitToGenTryPromise = createRefactor({
|
|
|
3732
3956
|
apply: fn("asyncAwaitToGenTryPromise.apply")(function* (sourceFile, textRange) {
|
|
3733
3957
|
const ts = yield* service(TypeScriptApi);
|
|
3734
3958
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3959
|
+
const typeParser = yield* service(TypeParser);
|
|
3735
3960
|
const maybeNode = pipe(
|
|
3736
3961
|
yield* getAncestorNodesInRange(sourceFile, textRange),
|
|
3737
3962
|
filter(
|
|
@@ -3754,7 +3979,7 @@ var asyncAwaitToGenTryPromise = createRefactor({
|
|
|
3754
3979
|
findImportedModuleIdentifier(
|
|
3755
3980
|
sourceFile,
|
|
3756
3981
|
(node2) => pipe(
|
|
3757
|
-
importedEffectModule(node2),
|
|
3982
|
+
typeParser.importedEffectModule(node2),
|
|
3758
3983
|
option,
|
|
3759
3984
|
map4(isSome2)
|
|
3760
3985
|
)
|
|
@@ -3831,17 +4056,18 @@ var effectGenToFn = createRefactor({
|
|
|
3831
4056
|
description: "Convert to Effect.fn",
|
|
3832
4057
|
apply: fn("effectGenToFn.apply")(function* (sourceFile, textRange) {
|
|
3833
4058
|
const ts = yield* service(TypeScriptApi);
|
|
4059
|
+
const typeParser = yield* service(TypeParser);
|
|
3834
4060
|
const parseEffectGenNode = fn("asyncAwaitToGen.apply")(function* (node) {
|
|
3835
|
-
const
|
|
4061
|
+
const effectGen = yield* typeParser.effectGen(node);
|
|
3836
4062
|
let pipeArgs2 = ts.factory.createNodeArray([]);
|
|
3837
4063
|
let nodeToReplace2 = node;
|
|
3838
4064
|
while (nodeToReplace2.parent) {
|
|
3839
4065
|
const parent = nodeToReplace2.parent;
|
|
3840
4066
|
if (ts.isConciseBody(nodeToReplace2) && ts.isArrowFunction(parent) && parent.body === nodeToReplace2) {
|
|
3841
|
-
return { ...
|
|
4067
|
+
return { ...effectGen, pipeArgs: pipeArgs2, nodeToReplace: parent };
|
|
3842
4068
|
}
|
|
3843
4069
|
if ((ts.isFunctionDeclaration(parent) || ts.isMethodDeclaration(parent)) && parent.body === nodeToReplace2) {
|
|
3844
|
-
return { ...
|
|
4070
|
+
return { ...effectGen, pipeArgs: pipeArgs2, nodeToReplace: parent };
|
|
3845
4071
|
}
|
|
3846
4072
|
if (ts.isBlock(parent) && parent.statements.length === 1 && parent.statements[0] === nodeToReplace2) {
|
|
3847
4073
|
nodeToReplace2 = parent;
|
|
@@ -3978,6 +4204,7 @@ var _findSchemaVariableDeclaration = fn(
|
|
|
3978
4204
|
function* (sourceFile, textRange) {
|
|
3979
4205
|
const ts = yield* service(TypeScriptApi);
|
|
3980
4206
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
4207
|
+
const typeParser = yield* service(TypeParser);
|
|
3981
4208
|
const findSchema = fn("makeSchemaOpaque.apply.findSchema")(
|
|
3982
4209
|
function* (node) {
|
|
3983
4210
|
if (!ts.isVariableDeclaration(node)) {
|
|
@@ -3996,7 +4223,7 @@ var _findSchemaVariableDeclaration = fn(
|
|
|
3996
4223
|
return yield* fail("parent not variable declaration statement");
|
|
3997
4224
|
}
|
|
3998
4225
|
const type = typeChecker.getTypeAtLocation(initializer);
|
|
3999
|
-
const types = yield* effectSchemaType(type, initializer);
|
|
4226
|
+
const types = yield* typeParser.effectSchemaType(type, initializer);
|
|
4000
4227
|
return { identifier, variableStatement, variableDeclarationList, types };
|
|
4001
4228
|
}
|
|
4002
4229
|
);
|
|
@@ -4343,8 +4570,9 @@ var removeUnnecessaryEffectGen = createRefactor({
|
|
|
4343
4570
|
name: "removeUnnecessaryEffectGen",
|
|
4344
4571
|
description: "Remove unnecessary Effect.gen",
|
|
4345
4572
|
apply: fn("removeUnnecessaryEffectGen.apply")(function* (sourceFile, textRange) {
|
|
4573
|
+
const typeParser = yield* service(TypeParser);
|
|
4346
4574
|
for (const nodeToReplace of yield* getAncestorNodesInRange(sourceFile, textRange)) {
|
|
4347
|
-
const maybeNode = yield* option(unnecessaryEffectGen(nodeToReplace));
|
|
4575
|
+
const maybeNode = yield* option(typeParser.unnecessaryEffectGen(nodeToReplace));
|
|
4348
4576
|
if (isNone2(maybeNode)) continue;
|
|
4349
4577
|
const replacementNode = maybeNode.value.replacementNode;
|
|
4350
4578
|
return {
|
|
@@ -4717,12 +4945,21 @@ var processNode = (node, isVirtualTypeNode) => gen2(function* () {
|
|
|
4717
4945
|
[ts.factory.createObjectLiteralExpression(properties, true)].concat(records)
|
|
4718
4946
|
);
|
|
4719
4947
|
}
|
|
4948
|
+
if (ts.isParenthesizedTypeNode(node)) {
|
|
4949
|
+
return yield* processNode(node.type, isVirtualTypeNode);
|
|
4950
|
+
}
|
|
4720
4951
|
if (ts.isTypeQueryNode(node)) {
|
|
4721
4952
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
4722
4953
|
const type = typeChecker.getTypeAtLocation(node.exprName);
|
|
4723
4954
|
const typeNode = typeChecker.typeToTypeNode(type, void 0, ts.NodeBuilderFlags.NoTruncation);
|
|
4724
4955
|
if (typeNode) return yield* processNode(typeNode, true);
|
|
4725
4956
|
}
|
|
4957
|
+
if (!isVirtualTypeNode && ts.isIndexedAccessTypeNode(node) && ts.isParenthesizedTypeNode(node.objectType) && ts.isTypeQueryNode(node.objectType.type) && ts.isTypeOperatorNode(node.indexType) && node.indexType.operator === ts.SyntaxKind.KeyOfKeyword && ts.isTypeQueryNode(node.indexType.type) && node.indexType.type.exprName.getText().trim() === node.objectType.type.exprName.getText().trim()) {
|
|
4958
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
4959
|
+
const type = typeChecker.getTypeAtLocation(node);
|
|
4960
|
+
const typeNode = typeChecker.typeToTypeNode(type, void 0, ts.NodeBuilderFlags.NoTruncation);
|
|
4961
|
+
if (typeNode) return yield* processNode(typeNode, true);
|
|
4962
|
+
}
|
|
4726
4963
|
if (ts.isTypeReferenceNode(node)) {
|
|
4727
4964
|
const parsedName = entityNameToDataTypeName(node.typeName);
|
|
4728
4965
|
if (isSome2(parsedName)) {
|
|
@@ -5018,13 +5255,14 @@ var wrapWithEffectGen = createRefactor({
|
|
|
5018
5255
|
apply: fn("wrapWithEffectGen.apply")(function* (sourceFile, textRange) {
|
|
5019
5256
|
const ts = yield* service(TypeScriptApi);
|
|
5020
5257
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
5258
|
+
const typeParser = yield* service(TypeParser);
|
|
5021
5259
|
const findEffectToWrap = fn("wrapWithEffectGen.apply.findEffectToWrap")(
|
|
5022
5260
|
function* (node) {
|
|
5023
5261
|
if (!ts.isExpression(node)) return yield* fail("is not an expression");
|
|
5024
5262
|
const parent = node.parent;
|
|
5025
5263
|
if (parent != null && ts.isVariableDeclaration(parent) && parent.initializer !== node) return yield* fail("is LHS of variable declaration");
|
|
5026
5264
|
const type = typeChecker.getTypeAtLocation(node);
|
|
5027
|
-
yield* effectType(type, node);
|
|
5265
|
+
yield* typeParser.effectType(type, node);
|
|
5028
5266
|
return node;
|
|
5029
5267
|
}
|
|
5030
5268
|
);
|
|
@@ -5035,19 +5273,35 @@ var wrapWithEffectGen = createRefactor({
|
|
|
5035
5273
|
option
|
|
5036
5274
|
);
|
|
5037
5275
|
if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
|
|
5276
|
+
const effectModuleIdentifier = match2(
|
|
5277
|
+
yield* option(
|
|
5278
|
+
findImportedModuleIdentifier(
|
|
5279
|
+
sourceFile,
|
|
5280
|
+
(node) => pipe(
|
|
5281
|
+
typeParser.importedEffectModule(node),
|
|
5282
|
+
option,
|
|
5283
|
+
map4(isSome2)
|
|
5284
|
+
)
|
|
5285
|
+
)
|
|
5286
|
+
),
|
|
5287
|
+
{
|
|
5288
|
+
onNone: () => "Effect",
|
|
5289
|
+
onSome: (node) => node.text
|
|
5290
|
+
}
|
|
5291
|
+
);
|
|
5038
5292
|
return {
|
|
5039
5293
|
kind: "refactor.rewrite.effect.wrapWithEffectGen",
|
|
5040
5294
|
description: `Wrap with Effect.gen`,
|
|
5041
5295
|
apply: pipe(
|
|
5042
5296
|
gen2(function* () {
|
|
5043
5297
|
const changeTracker = yield* service(ChangeTracker);
|
|
5044
|
-
const
|
|
5298
|
+
const effectGen = yield* pipe(
|
|
5045
5299
|
createEffectGenCallExpressionWithBlock(
|
|
5046
|
-
|
|
5300
|
+
effectModuleIdentifier,
|
|
5047
5301
|
yield* createReturnYieldStarStatement(maybeNode.value)
|
|
5048
5302
|
)
|
|
5049
5303
|
);
|
|
5050
|
-
changeTracker.replaceNode(sourceFile, maybeNode.value,
|
|
5304
|
+
changeTracker.replaceNode(sourceFile, maybeNode.value, effectGen);
|
|
5051
5305
|
}),
|
|
5052
5306
|
provideService(TypeScriptApi, ts),
|
|
5053
5307
|
provideService(TypeCheckerApi, typeChecker)
|
|
@@ -5055,26 +5309,6 @@ var wrapWithEffectGen = createRefactor({
|
|
|
5055
5309
|
};
|
|
5056
5310
|
})
|
|
5057
5311
|
});
|
|
5058
|
-
var getEffectModuleIdentifierName = fn("getEffectModuleIdentifierName")(
|
|
5059
|
-
function* (sourceFile) {
|
|
5060
|
-
return match2(
|
|
5061
|
-
yield* option(
|
|
5062
|
-
findImportedModuleIdentifier(
|
|
5063
|
-
sourceFile,
|
|
5064
|
-
(node) => pipe(
|
|
5065
|
-
importedEffectModule(node),
|
|
5066
|
-
option,
|
|
5067
|
-
map4(isSome2)
|
|
5068
|
-
)
|
|
5069
|
-
)
|
|
5070
|
-
),
|
|
5071
|
-
{
|
|
5072
|
-
onNone: () => "Effect",
|
|
5073
|
-
onSome: (node) => node.text
|
|
5074
|
-
}
|
|
5075
|
-
);
|
|
5076
|
-
}
|
|
5077
|
-
);
|
|
5078
5312
|
|
|
5079
5313
|
// src/refactors/wrapWithPipe.ts
|
|
5080
5314
|
var wrapWithPipe = createRefactor({
|
|
@@ -5139,6 +5373,7 @@ var init = (modules) => {
|
|
|
5139
5373
|
function runNano(program) {
|
|
5140
5374
|
return (fa) => pipe(
|
|
5141
5375
|
fa,
|
|
5376
|
+
provideService(TypeParser, make4(modules.typescript, program.getTypeChecker())),
|
|
5142
5377
|
provideService(TypeScriptProgram, program),
|
|
5143
5378
|
provideService(TypeCheckerApi, program.getTypeChecker()),
|
|
5144
5379
|
provideService(
|
|
@@ -5349,15 +5584,17 @@ var init = (modules) => {
|
|
|
5349
5584
|
};
|
|
5350
5585
|
proxy.getDefinitionAndBoundSpan = (fileName, position, ...args) => {
|
|
5351
5586
|
const applicableDefinition = languageService.getDefinitionAndBoundSpan(fileName, position, ...args);
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5587
|
+
if (languageServicePluginOptions.goto) {
|
|
5588
|
+
const program = languageService.getProgram();
|
|
5589
|
+
if (program) {
|
|
5590
|
+
const sourceFile = program.getSourceFile(fileName);
|
|
5591
|
+
if (sourceFile) {
|
|
5592
|
+
return pipe(
|
|
5593
|
+
goto(applicableDefinition, sourceFile, position),
|
|
5594
|
+
runNano(program),
|
|
5595
|
+
Either_exports.getOrElse(() => applicableDefinition)
|
|
5596
|
+
);
|
|
5597
|
+
}
|
|
5361
5598
|
}
|
|
5362
5599
|
}
|
|
5363
5600
|
return applicableDefinition;
|