@effect/language-service 0.21.8 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -6
- package/index.js +617 -433
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +258 -149
- package/transform.js.map +1 -1
package/transform.js
CHANGED
|
@@ -754,8 +754,6 @@ var fromIterable = (collection) => Array.isArray(collection) ? collection : Arra
|
|
|
754
754
|
var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
|
|
755
755
|
var appendAll = /* @__PURE__ */ dual(2, (self, that) => fromIterable(self).concat(fromIterable(that)));
|
|
756
756
|
var isArray = Array.isArray;
|
|
757
|
-
var isEmptyArray = (self) => self.length === 0;
|
|
758
|
-
var isEmptyReadonlyArray = isEmptyArray;
|
|
759
757
|
var sort = /* @__PURE__ */ dual(2, (self, O) => {
|
|
760
758
|
const out = Array.from(self);
|
|
761
759
|
out.sort(O);
|
|
@@ -777,20 +775,6 @@ var intersectionWith = (isEquivalent) => {
|
|
|
777
775
|
var intersection = /* @__PURE__ */ intersectionWith(_equivalence);
|
|
778
776
|
var empty = () => [];
|
|
779
777
|
var map2 = /* @__PURE__ */ dual(2, (self, f) => self.map(f));
|
|
780
|
-
var flatMap = /* @__PURE__ */ dual(2, (self, f) => {
|
|
781
|
-
if (isEmptyReadonlyArray(self)) {
|
|
782
|
-
return [];
|
|
783
|
-
}
|
|
784
|
-
const out = [];
|
|
785
|
-
for (let i = 0; i < self.length; i++) {
|
|
786
|
-
const inner = f(self[i], i);
|
|
787
|
-
for (let j = 0; j < inner.length; j++) {
|
|
788
|
-
out.push(inner[j]);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
return out;
|
|
792
|
-
});
|
|
793
|
-
var flatten = /* @__PURE__ */ flatMap(identity);
|
|
794
778
|
var filter = /* @__PURE__ */ dual(2, (self, predicate) => {
|
|
795
779
|
const as = fromIterable(self);
|
|
796
780
|
const out = [];
|
|
@@ -803,29 +787,11 @@ var filter = /* @__PURE__ */ dual(2, (self, predicate) => {
|
|
|
803
787
|
});
|
|
804
788
|
|
|
805
789
|
// src/core/Nano.ts
|
|
806
|
-
var NanoInternalSuccessProto = {
|
|
807
|
-
_tag: "Right"
|
|
808
|
-
};
|
|
809
790
|
function makeInternalSuccess(value) {
|
|
810
|
-
|
|
811
|
-
result.value = value;
|
|
812
|
-
return result;
|
|
791
|
+
return { _tag: "Right", value };
|
|
813
792
|
}
|
|
814
|
-
var NanoInternalFailureProto = {
|
|
815
|
-
_tag: "Left"
|
|
816
|
-
};
|
|
817
|
-
function makeInternalFailure(value) {
|
|
818
|
-
const result = Object.create(NanoInternalFailureProto);
|
|
819
|
-
result.value = value;
|
|
820
|
-
return result;
|
|
821
|
-
}
|
|
822
|
-
var NanoInternalDefectProto = {
|
|
823
|
-
_tag: "Defect"
|
|
824
|
-
};
|
|
825
793
|
function makeInternalDefect(value) {
|
|
826
|
-
|
|
827
|
-
result.value = value;
|
|
828
|
-
return result;
|
|
794
|
+
return { _tag: "Defect", value };
|
|
829
795
|
}
|
|
830
796
|
var NanoDefectException = class {
|
|
831
797
|
constructor(message) {
|
|
@@ -840,17 +806,14 @@ var NanoTag = class {
|
|
|
840
806
|
};
|
|
841
807
|
var Tag = (identifier) => new NanoTag(identifier);
|
|
842
808
|
var contextEmpty = { value: {} };
|
|
843
|
-
var Proto = {
|
|
844
|
-
run: () => {
|
|
845
|
-
},
|
|
846
|
-
[Symbol.iterator]() {
|
|
847
|
-
return new SingleShotGen(new YieldWrap(this));
|
|
848
|
-
}
|
|
849
|
-
};
|
|
850
809
|
function make2(run2) {
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
|
|
810
|
+
const nano = {
|
|
811
|
+
run: run2,
|
|
812
|
+
[Symbol.iterator]() {
|
|
813
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
return nano;
|
|
854
817
|
}
|
|
855
818
|
var unsafeRun = (fa) => {
|
|
856
819
|
const program = provideService(internalNanoCache, {})(fa);
|
|
@@ -871,10 +834,34 @@ var run = (fa) => {
|
|
|
871
834
|
return left2(new NanoDefectException(e));
|
|
872
835
|
}
|
|
873
836
|
};
|
|
874
|
-
var succeed = (value) =>
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
837
|
+
var succeed = (value) => {
|
|
838
|
+
const nano = {
|
|
839
|
+
run: () => ({ _tag: "Right", value }),
|
|
840
|
+
[Symbol.iterator]() {
|
|
841
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
return nano;
|
|
845
|
+
};
|
|
846
|
+
var fail = (value) => {
|
|
847
|
+
const nano = {
|
|
848
|
+
run: () => ({ _tag: "Left", value }),
|
|
849
|
+
[Symbol.iterator]() {
|
|
850
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
return nano;
|
|
854
|
+
};
|
|
855
|
+
var sync = (value) => {
|
|
856
|
+
const nano = {
|
|
857
|
+
run: () => ({ _tag: "Right", value: value() }),
|
|
858
|
+
[Symbol.iterator]() {
|
|
859
|
+
return new SingleShotGen(new YieldWrap(this));
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
return nano;
|
|
863
|
+
};
|
|
864
|
+
var flatMap = dual(2, (fa, f) => make2((ctx) => {
|
|
878
865
|
const result = fa.run(ctx);
|
|
879
866
|
if (result._tag !== "Right") return result;
|
|
880
867
|
return f(result.value).run(ctx);
|
|
@@ -965,8 +952,9 @@ function cachedBy(fa, key, lookupKey) {
|
|
|
965
952
|
cacheObj[key] = cache;
|
|
966
953
|
}
|
|
967
954
|
const lookup = lookupKey(...args);
|
|
968
|
-
|
|
969
|
-
|
|
955
|
+
const cached2 = cache.get(lookup);
|
|
956
|
+
if (cached2 !== void 0) {
|
|
957
|
+
return cached2;
|
|
970
958
|
}
|
|
971
959
|
const result = fa(...args).run(ctx);
|
|
972
960
|
cache.set(lookup, result);
|
|
@@ -996,7 +984,8 @@ function parse(config) {
|
|
|
996
984
|
quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : true,
|
|
997
985
|
completions: isObject(config) && hasProperty(config, "completions") && isBoolean(config.completions) ? config.completions : true,
|
|
998
986
|
goto: isObject(config) && hasProperty(config, "goto") && isBoolean(config.goto) ? config.goto : true,
|
|
999
|
-
allowedDuplicatedPackages: isObject(config) && hasProperty(config, "allowedDuplicatedPackages") && isArray(config.allowedDuplicatedPackages) && config.allowedDuplicatedPackages.every(isString) ? config.allowedDuplicatedPackages.map((_) => _.toLowerCase()) : []
|
|
987
|
+
allowedDuplicatedPackages: isObject(config) && hasProperty(config, "allowedDuplicatedPackages") && isArray(config.allowedDuplicatedPackages) && config.allowedDuplicatedPackages.every(isString) ? config.allowedDuplicatedPackages.map((_) => _.toLowerCase()) : [],
|
|
988
|
+
namespaceImportPackages: isObject(config) && hasProperty(config, "namespaceImportPackages") && isArray(config.namespaceImportPackages) && config.namespaceImportPackages.every(isString) ? config.namespaceImportPackages.map((_) => _.toLowerCase()) : []
|
|
1000
989
|
};
|
|
1001
990
|
}
|
|
1002
991
|
|
|
@@ -1028,6 +1017,20 @@ function parsePackageContentNameAndVersionFromScope(v) {
|
|
|
1028
1017
|
packageDirectory: packageJsonScope.packageDirectory
|
|
1029
1018
|
};
|
|
1030
1019
|
}
|
|
1020
|
+
function makeGetModuleSpecifier(ts) {
|
|
1021
|
+
if (!(hasProperty(ts, "moduleSpecifiers") && hasProperty(ts.moduleSpecifiers, "getModuleSpecifier") && isFunction2(ts.moduleSpecifiers.getModuleSpecifier))) return;
|
|
1022
|
+
const _internal = ts.moduleSpecifiers.getModuleSpecifier;
|
|
1023
|
+
return (compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, options) => {
|
|
1024
|
+
return _internal(
|
|
1025
|
+
compilerOptions,
|
|
1026
|
+
importingSourceFile,
|
|
1027
|
+
importingSourceFileName,
|
|
1028
|
+
toFileName,
|
|
1029
|
+
host,
|
|
1030
|
+
options
|
|
1031
|
+
);
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1031
1034
|
|
|
1032
1035
|
// src/core/LSP.ts
|
|
1033
1036
|
var RefactorNotApplicableError = class {
|
|
@@ -1043,40 +1046,9 @@ var getSemanticDiagnosticsWithCodeFixes = fn(
|
|
|
1043
1046
|
let effectCodeFixes = [];
|
|
1044
1047
|
const executor = yield* createDiagnosticExecutor(sourceFile);
|
|
1045
1048
|
for (const rule of rules) {
|
|
1046
|
-
const
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
pipe(
|
|
1050
|
-
result.value,
|
|
1051
|
-
map2((_) => ({
|
|
1052
|
-
file: sourceFile,
|
|
1053
|
-
start: _.node.getStart(sourceFile),
|
|
1054
|
-
length: _.node.getEnd() - _.node.getStart(sourceFile),
|
|
1055
|
-
messageText: _.messageText,
|
|
1056
|
-
category: _.category,
|
|
1057
|
-
code: rule.code,
|
|
1058
|
-
source: "effect"
|
|
1059
|
-
}))
|
|
1060
|
-
)
|
|
1061
|
-
);
|
|
1062
|
-
effectCodeFixes = effectCodeFixes.concat(
|
|
1063
|
-
pipe(
|
|
1064
|
-
result.value,
|
|
1065
|
-
map2(
|
|
1066
|
-
(_) => map2(
|
|
1067
|
-
_.fixes,
|
|
1068
|
-
(fix) => ({
|
|
1069
|
-
...fix,
|
|
1070
|
-
code: rule.code,
|
|
1071
|
-
start: _.node.getStart(sourceFile),
|
|
1072
|
-
end: _.node.getEnd()
|
|
1073
|
-
})
|
|
1074
|
-
)
|
|
1075
|
-
),
|
|
1076
|
-
flatten
|
|
1077
|
-
)
|
|
1078
|
-
);
|
|
1079
|
-
}
|
|
1049
|
+
const { codeFixes, diagnostics: diagnostics2 } = yield* executor.execute(rule);
|
|
1050
|
+
effectDiagnostics = effectDiagnostics.concat(diagnostics2);
|
|
1051
|
+
effectCodeFixes = effectCodeFixes.concat(codeFixes);
|
|
1080
1052
|
}
|
|
1081
1053
|
return {
|
|
1082
1054
|
diagnostics: effectDiagnostics,
|
|
@@ -1207,12 +1179,14 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
|
|
|
1207
1179
|
suggestion: ts.DiagnosticCategory.Suggestion
|
|
1208
1180
|
};
|
|
1209
1181
|
const execute = fn("LSP.ruleExecutor")(function* (rule) {
|
|
1182
|
+
const diagnostics2 = [];
|
|
1183
|
+
const codeFixes = [];
|
|
1210
1184
|
const ruleNameLowered = rule.name.toLowerCase();
|
|
1211
|
-
if (skippedRules.indexOf(ruleNameLowered) > -1) return
|
|
1185
|
+
if (skippedRules.indexOf(ruleNameLowered) > -1) return { diagnostics: diagnostics2, codeFixes };
|
|
1212
1186
|
const fixByDisableNextLine = (_) => ({
|
|
1213
1187
|
fixName: rule.name + "_skipNextLine",
|
|
1214
1188
|
description: "Disable " + rule.name + " for this line",
|
|
1215
|
-
apply:
|
|
1189
|
+
apply: flatMap(
|
|
1216
1190
|
service(ChangeTracker),
|
|
1217
1191
|
(changeTracker) => sync(() => {
|
|
1218
1192
|
const disableAtNode = findParentStatementForDisableNextLine(_.node);
|
|
@@ -1229,7 +1203,7 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
|
|
|
1229
1203
|
const fixByDisableEntireFile = {
|
|
1230
1204
|
fixName: rule.name + "_skipFile",
|
|
1231
1205
|
description: "Disable " + rule.name + " for this entire file",
|
|
1232
|
-
apply:
|
|
1206
|
+
apply: flatMap(
|
|
1233
1207
|
service(ChangeTracker),
|
|
1234
1208
|
(changeTracker) => sync(
|
|
1235
1209
|
() => changeTracker.insertText(
|
|
@@ -1241,16 +1215,15 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
|
|
|
1241
1215
|
)
|
|
1242
1216
|
)
|
|
1243
1217
|
};
|
|
1244
|
-
|
|
1218
|
+
const applicableDiagnostics = [];
|
|
1245
1219
|
yield* rule.apply(sourceFile, (entry) => {
|
|
1246
|
-
|
|
1220
|
+
applicableDiagnostics.push({
|
|
1247
1221
|
...entry,
|
|
1248
1222
|
fixes: entry.fixes.concat([fixByDisableNextLine(entry), fixByDisableEntireFile])
|
|
1249
1223
|
});
|
|
1250
1224
|
});
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
let newLevel = pluginOptions.diagnosticSeverity[ruleNameLowered];
|
|
1225
|
+
for (const emitted of applicableDiagnostics.slice(0)) {
|
|
1226
|
+
let newLevel = pluginOptions.diagnosticSeverity[ruleNameLowered] || rule.severity;
|
|
1254
1227
|
const lineOverride = (lineOverrides[ruleNameLowered] || []).find(
|
|
1255
1228
|
(_) => _.pos < emitted.node.getStart(sourceFile) && _.end >= emitted.node.getEnd()
|
|
1256
1229
|
);
|
|
@@ -1262,13 +1235,26 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
|
|
|
1262
1235
|
);
|
|
1263
1236
|
if (sectionOverride) newLevel = sectionOverride.level;
|
|
1264
1237
|
}
|
|
1265
|
-
if (newLevel
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1238
|
+
if (!(newLevel in levelToDiagnosticCategory)) continue;
|
|
1239
|
+
diagnostics2.push({
|
|
1240
|
+
file: sourceFile,
|
|
1241
|
+
start: emitted.node.getStart(sourceFile),
|
|
1242
|
+
length: emitted.node.getEnd() - emitted.node.getStart(sourceFile),
|
|
1243
|
+
messageText: emitted.messageText,
|
|
1244
|
+
category: levelToDiagnosticCategory[newLevel],
|
|
1245
|
+
code: rule.code,
|
|
1246
|
+
source: "effect"
|
|
1247
|
+
});
|
|
1248
|
+
for (const fix of emitted.fixes) {
|
|
1249
|
+
codeFixes.push({
|
|
1250
|
+
...fix,
|
|
1251
|
+
code: rule.code,
|
|
1252
|
+
start: emitted.node.getStart(sourceFile),
|
|
1253
|
+
end: emitted.node.getEnd()
|
|
1254
|
+
});
|
|
1269
1255
|
}
|
|
1270
1256
|
}
|
|
1271
|
-
return
|
|
1257
|
+
return { diagnostics: diagnostics2, codeFixes };
|
|
1272
1258
|
});
|
|
1273
1259
|
return { execute };
|
|
1274
1260
|
}
|
|
@@ -1525,6 +1511,15 @@ var appendToUniqueTypesMap = fn(
|
|
|
1525
1511
|
};
|
|
1526
1512
|
}
|
|
1527
1513
|
);
|
|
1514
|
+
function makeResolveExternalModuleName(typeChecker) {
|
|
1515
|
+
if (!(hasProperty(typeChecker, "resolveExternalModuleName") && isFunction(typeChecker.resolveExternalModuleName))) {
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
const _internal = typeChecker.resolveExternalModuleName;
|
|
1519
|
+
return (moduleSpecifier) => {
|
|
1520
|
+
return _internal(moduleSpecifier);
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1528
1523
|
|
|
1529
1524
|
// src/core/AST.ts
|
|
1530
1525
|
function collectSelfAndAncestorNodesInRange(node, textRange) {
|
|
@@ -2359,8 +2354,8 @@ var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
|
2359
2354
|
var duplicatePackage = createDiagnostic({
|
|
2360
2355
|
name: "duplicatePackage",
|
|
2361
2356
|
code: 6,
|
|
2357
|
+
severity: "warning",
|
|
2362
2358
|
apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
2363
|
-
const ts = yield* service(TypeScriptApi);
|
|
2364
2359
|
const program = yield* service(TypeScriptProgram);
|
|
2365
2360
|
const options = yield* service(LanguageServicePluginOptions);
|
|
2366
2361
|
if (sourceFile.statements.length < 1) return;
|
|
@@ -2389,7 +2384,6 @@ var duplicatePackage = createDiagnostic({
|
|
|
2389
2384
|
const versions = Object.keys(resolvedPackages[packageName]);
|
|
2390
2385
|
report({
|
|
2391
2386
|
node: sourceFile.statements[0],
|
|
2392
|
-
category: ts.DiagnosticCategory.Warning,
|
|
2393
2387
|
messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
|
|
2394
2388
|
Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
|
|
2395
2389
|
If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
@@ -2406,6 +2400,7 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
2406
2400
|
var floatingEffect = createDiagnostic({
|
|
2407
2401
|
name: "floatingEffect",
|
|
2408
2402
|
code: 3,
|
|
2403
|
+
severity: "error",
|
|
2409
2404
|
apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
|
|
2410
2405
|
const ts = yield* service(TypeScriptApi);
|
|
2411
2406
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -2438,7 +2433,6 @@ var floatingEffect = createDiagnostic({
|
|
|
2438
2433
|
if (isNone2(allowedFloatingEffects)) {
|
|
2439
2434
|
report({
|
|
2440
2435
|
node,
|
|
2441
|
-
category: ts.DiagnosticCategory.Error,
|
|
2442
2436
|
messageText: `Effect must be yielded or assigned to a variable.`,
|
|
2443
2437
|
fixes: []
|
|
2444
2438
|
});
|
|
@@ -2452,6 +2446,7 @@ var floatingEffect = createDiagnostic({
|
|
|
2452
2446
|
var genericEffectServices = createDiagnostic({
|
|
2453
2447
|
name: "genericEffectServices",
|
|
2454
2448
|
code: 10,
|
|
2449
|
+
severity: "warning",
|
|
2455
2450
|
apply: fn("genericEffectServices.apply")(function* (sourceFile, report) {
|
|
2456
2451
|
const ts = yield* service(TypeScriptApi);
|
|
2457
2452
|
const typeParser = yield* service(TypeParser);
|
|
@@ -2481,7 +2476,6 @@ var genericEffectServices = createDiagnostic({
|
|
|
2481
2476
|
map3(() => {
|
|
2482
2477
|
report({
|
|
2483
2478
|
node: reportAt,
|
|
2484
|
-
category: ts.DiagnosticCategory.Warning,
|
|
2485
2479
|
messageText: `Effect Services with type parameters are not supported because they cannot be properly discriminated at runtime, which may cause unexpected behavior.`,
|
|
2486
2480
|
fixes: []
|
|
2487
2481
|
});
|
|
@@ -2494,10 +2488,124 @@ var genericEffectServices = createDiagnostic({
|
|
|
2494
2488
|
})
|
|
2495
2489
|
});
|
|
2496
2490
|
|
|
2491
|
+
// src/diagnostics/importFromBarrel.ts
|
|
2492
|
+
var importFromBarrel = createDiagnostic({
|
|
2493
|
+
name: "importFromBarrel",
|
|
2494
|
+
code: 12,
|
|
2495
|
+
severity: "off",
|
|
2496
|
+
apply: fn("importFromBarrel.apply")(function* (sourceFile, report) {
|
|
2497
|
+
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
2498
|
+
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return;
|
|
2499
|
+
const ts = yield* service(TypeScriptApi);
|
|
2500
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
2501
|
+
const program = yield* service(TypeScriptProgram);
|
|
2502
|
+
const isImportedFromBarrelExport = (element, languageServicePluginOptions2) => {
|
|
2503
|
+
const getModuleSpecifier = makeGetModuleSpecifier(ts);
|
|
2504
|
+
const resolveExternalModuleName = makeResolveExternalModuleName(typeChecker);
|
|
2505
|
+
if (!(getModuleSpecifier && resolveExternalModuleName)) return;
|
|
2506
|
+
const importDeclaration = ts.findAncestor(element, (node) => ts.isImportDeclaration(node));
|
|
2507
|
+
if (!importDeclaration) return;
|
|
2508
|
+
if (!ts.isStringLiteral(importDeclaration.moduleSpecifier)) return;
|
|
2509
|
+
const importClause = importDeclaration.importClause;
|
|
2510
|
+
if (!importClause) return;
|
|
2511
|
+
const namedBindings = importClause.namedBindings;
|
|
2512
|
+
if (!namedBindings) return;
|
|
2513
|
+
if (!ts.isNamedImports(namedBindings)) return;
|
|
2514
|
+
const barrelModuleName = importDeclaration.moduleSpecifier.text;
|
|
2515
|
+
if (languageServicePluginOptions2.namespaceImportPackages.indexOf(barrelModuleName.toLowerCase()) === -1) return;
|
|
2516
|
+
const moduleSymbol = resolveExternalModuleName(importDeclaration.moduleSpecifier);
|
|
2517
|
+
if (!moduleSymbol) return;
|
|
2518
|
+
if (!moduleSymbol.exports) return;
|
|
2519
|
+
const sourceFile2 = importDeclaration.getSourceFile();
|
|
2520
|
+
const nodeForSymbol = element.propertyName || element.name;
|
|
2521
|
+
if (!ts.isIdentifier(nodeForSymbol)) return;
|
|
2522
|
+
const importedName = nodeForSymbol.text;
|
|
2523
|
+
const reexportedSymbol = moduleSymbol.exports.get(ts.escapeLeadingUnderscores(importedName));
|
|
2524
|
+
if (!reexportedSymbol) return;
|
|
2525
|
+
if (!(reexportedSymbol.declarations && reexportedSymbol.declarations.length === 1)) return;
|
|
2526
|
+
const namespaceExport = reexportedSymbol.declarations[0];
|
|
2527
|
+
if (!ts.isNamespaceExport(namespaceExport)) return;
|
|
2528
|
+
const exportDeclaration = namespaceExport.parent;
|
|
2529
|
+
if (!ts.isExportDeclaration(exportDeclaration)) return;
|
|
2530
|
+
if (!exportDeclaration.moduleSpecifier) return;
|
|
2531
|
+
const originalModuleSymbol = resolveExternalModuleName(exportDeclaration.moduleSpecifier);
|
|
2532
|
+
if (!originalModuleSymbol) return;
|
|
2533
|
+
if (!originalModuleSymbol.valueDeclaration) return;
|
|
2534
|
+
const originalSourceFile = originalModuleSymbol.valueDeclaration.getSourceFile();
|
|
2535
|
+
const unbarrelledFileName = getModuleSpecifier(
|
|
2536
|
+
program.getCompilerOptions(),
|
|
2537
|
+
sourceFile2,
|
|
2538
|
+
sourceFile2.fileName,
|
|
2539
|
+
originalSourceFile.fileName,
|
|
2540
|
+
program
|
|
2541
|
+
);
|
|
2542
|
+
if (unbarrelledFileName.toLowerCase().indexOf(barrelModuleName.toLowerCase() + "/") === -1) return;
|
|
2543
|
+
return { unbarrelledFileName, importedName, barrelModuleName, importClause, namedBindings, importDeclaration };
|
|
2544
|
+
};
|
|
2545
|
+
const nodeToVisit = [];
|
|
2546
|
+
const appendNodeToVisit = (node) => {
|
|
2547
|
+
nodeToVisit.push(node);
|
|
2548
|
+
return void 0;
|
|
2549
|
+
};
|
|
2550
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
2551
|
+
while (nodeToVisit.length > 0) {
|
|
2552
|
+
const node = nodeToVisit.shift();
|
|
2553
|
+
const parent = node.parent;
|
|
2554
|
+
if (!(ts.isImportSpecifier(node) && ts.isNamedImports(parent))) {
|
|
2555
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
2556
|
+
continue;
|
|
2557
|
+
}
|
|
2558
|
+
const result = isImportedFromBarrelExport(node, languageServicePluginOptions);
|
|
2559
|
+
if (!result) continue;
|
|
2560
|
+
const { barrelModuleName, importClause, importDeclaration, importedName, namedBindings, unbarrelledFileName } = result;
|
|
2561
|
+
report({
|
|
2562
|
+
node,
|
|
2563
|
+
messageText: `Importing from barrel module ${barrelModuleName} is not allowed.`,
|
|
2564
|
+
fixes: [
|
|
2565
|
+
{
|
|
2566
|
+
fixName: "replaceWithUnbarrelledImport",
|
|
2567
|
+
description: `Import * as ${importedName} from ${unbarrelledFileName}`,
|
|
2568
|
+
apply: gen(function* () {
|
|
2569
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
2570
|
+
const newImport = ts.factory.createImportDeclaration(
|
|
2571
|
+
void 0,
|
|
2572
|
+
ts.factory.createImportClause(
|
|
2573
|
+
importClause.isTypeOnly || node.isTypeOnly,
|
|
2574
|
+
void 0,
|
|
2575
|
+
ts.factory.createNamespaceImport(ts.factory.createIdentifier(importedName))
|
|
2576
|
+
),
|
|
2577
|
+
ts.factory.createStringLiteral(unbarrelledFileName)
|
|
2578
|
+
);
|
|
2579
|
+
if (namedBindings.elements.length === 1) {
|
|
2580
|
+
changeTracker.replaceNode(
|
|
2581
|
+
sourceFile,
|
|
2582
|
+
importDeclaration,
|
|
2583
|
+
newImport
|
|
2584
|
+
);
|
|
2585
|
+
} else {
|
|
2586
|
+
changeTracker.insertNodeAfter(sourceFile, importDeclaration, newImport);
|
|
2587
|
+
changeTracker.replaceNode(
|
|
2588
|
+
sourceFile,
|
|
2589
|
+
namedBindings,
|
|
2590
|
+
ts.factory.updateNamedImports(
|
|
2591
|
+
namedBindings,
|
|
2592
|
+
namedBindings.elements.filter((e) => e !== node)
|
|
2593
|
+
)
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2596
|
+
})
|
|
2597
|
+
}
|
|
2598
|
+
]
|
|
2599
|
+
});
|
|
2600
|
+
}
|
|
2601
|
+
})
|
|
2602
|
+
});
|
|
2603
|
+
|
|
2497
2604
|
// src/diagnostics/leakingRequirements.ts
|
|
2498
2605
|
var leakingRequirements = createDiagnostic({
|
|
2499
2606
|
name: "leakingRequirements",
|
|
2500
2607
|
code: 8,
|
|
2608
|
+
severity: "suggestion",
|
|
2501
2609
|
apply: fn("leakingRequirements.apply")(function* (sourceFile, report) {
|
|
2502
2610
|
const ts = yield* service(TypeScriptApi);
|
|
2503
2611
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -2555,7 +2663,6 @@ var leakingRequirements = createDiagnostic({
|
|
|
2555
2663
|
if (requirements.length === 0) return;
|
|
2556
2664
|
report({
|
|
2557
2665
|
node,
|
|
2558
|
-
category: ts.DiagnosticCategory.Warning,
|
|
2559
2666
|
messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement.
|
|
2560
2667
|
If these requirements cannot be cached and are expected to be provided per method invocation (e.g. HttpServerRequest), you can safely disable this diagnostic for this line through quickfixes.
|
|
2561
2668
|
More info at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
|
|
@@ -2586,7 +2693,7 @@ More info at https://effect.website/docs/requirements-management/layers/#avoidin
|
|
|
2586
2693
|
for (const [type, reportAt] of typesToCheck) {
|
|
2587
2694
|
yield* pipe(
|
|
2588
2695
|
typeParser.contextTag(type, node),
|
|
2589
|
-
|
|
2696
|
+
flatMap(
|
|
2590
2697
|
({ Service }) => pipe(
|
|
2591
2698
|
parseLeakedRequirements(Service, node),
|
|
2592
2699
|
map3((requirements) => reportLeakingRequirements(reportAt, sort(requirements, typeOrder)))
|
|
@@ -2604,8 +2711,8 @@ More info at https://effect.website/docs/requirements-management/layers/#avoidin
|
|
|
2604
2711
|
var missingEffectContext = createDiagnostic({
|
|
2605
2712
|
name: "missingEffectContext",
|
|
2606
2713
|
code: 1,
|
|
2714
|
+
severity: "error",
|
|
2607
2715
|
apply: fn("missingEffectContext.apply")(function* (sourceFile, report) {
|
|
2608
|
-
const ts = yield* service(TypeScriptApi);
|
|
2609
2716
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2610
2717
|
const typeParser = yield* service(TypeParser);
|
|
2611
2718
|
const typeOrder = yield* deterministicTypeOrder;
|
|
@@ -2614,7 +2721,7 @@ var missingEffectContext = createDiagnostic({
|
|
|
2614
2721
|
typeParser.effectType(expectedType, node),
|
|
2615
2722
|
typeParser.effectType(realType, valueNode)
|
|
2616
2723
|
),
|
|
2617
|
-
|
|
2724
|
+
flatMap(
|
|
2618
2725
|
([expectedEffect, realEffect]) => getMissingTypeEntriesInTargetType(
|
|
2619
2726
|
realEffect.R,
|
|
2620
2727
|
expectedEffect.R
|
|
@@ -2624,23 +2731,24 @@ var missingEffectContext = createDiagnostic({
|
|
|
2624
2731
|
const sortTypes = sort(typeOrder);
|
|
2625
2732
|
const entries = yield* expectedAndRealType(sourceFile);
|
|
2626
2733
|
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
expectedType,
|
|
2631
|
-
valueNode,
|
|
2632
|
-
realType
|
|
2633
|
-
),
|
|
2634
|
-
orElse2(() => succeed([]))
|
|
2635
|
-
);
|
|
2636
|
-
if (missingContext.length > 0) {
|
|
2637
|
-
report(
|
|
2638
|
-
{
|
|
2734
|
+
if (expectedType !== realType) {
|
|
2735
|
+
yield* pipe(
|
|
2736
|
+
checkForMissingContextTypes(
|
|
2639
2737
|
node,
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2738
|
+
expectedType,
|
|
2739
|
+
valueNode,
|
|
2740
|
+
realType
|
|
2741
|
+
),
|
|
2742
|
+
map3(
|
|
2743
|
+
(missingTypes) => missingTypes.length > 0 ? report(
|
|
2744
|
+
{
|
|
2745
|
+
node,
|
|
2746
|
+
messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
|
|
2747
|
+
fixes: []
|
|
2748
|
+
}
|
|
2749
|
+
) : void 0
|
|
2750
|
+
),
|
|
2751
|
+
ignore
|
|
2644
2752
|
);
|
|
2645
2753
|
}
|
|
2646
2754
|
}
|
|
@@ -2651,8 +2759,8 @@ var missingEffectContext = createDiagnostic({
|
|
|
2651
2759
|
var missingEffectError = createDiagnostic({
|
|
2652
2760
|
name: "missingEffectError",
|
|
2653
2761
|
code: 1,
|
|
2762
|
+
severity: "error",
|
|
2654
2763
|
apply: fn("missingEffectError.apply")(function* (sourceFile, report) {
|
|
2655
|
-
const ts = yield* service(TypeScriptApi);
|
|
2656
2764
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2657
2765
|
const typeParser = yield* service(TypeParser);
|
|
2658
2766
|
const typeOrder = yield* deterministicTypeOrder;
|
|
@@ -2661,7 +2769,7 @@ var missingEffectError = createDiagnostic({
|
|
|
2661
2769
|
typeParser.effectType(expectedType, node),
|
|
2662
2770
|
typeParser.effectType(realType, valueNode)
|
|
2663
2771
|
),
|
|
2664
|
-
|
|
2772
|
+
flatMap(
|
|
2665
2773
|
([expectedEffect, realEffect]) => getMissingTypeEntriesInTargetType(
|
|
2666
2774
|
realEffect.E,
|
|
2667
2775
|
expectedEffect.E
|
|
@@ -2671,23 +2779,24 @@ var missingEffectError = createDiagnostic({
|
|
|
2671
2779
|
const sortTypes = sort(typeOrder);
|
|
2672
2780
|
const entries = yield* expectedAndRealType(sourceFile);
|
|
2673
2781
|
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
expectedType,
|
|
2678
|
-
valueNode,
|
|
2679
|
-
realType
|
|
2680
|
-
),
|
|
2681
|
-
orElse2(() => succeed([]))
|
|
2682
|
-
);
|
|
2683
|
-
if (missingContext.length > 0) {
|
|
2684
|
-
report(
|
|
2685
|
-
{
|
|
2782
|
+
if (expectedType !== realType) {
|
|
2783
|
+
yield* pipe(
|
|
2784
|
+
checkForMissingErrorTypes(
|
|
2686
2785
|
node,
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2786
|
+
expectedType,
|
|
2787
|
+
valueNode,
|
|
2788
|
+
realType
|
|
2789
|
+
),
|
|
2790
|
+
map3(
|
|
2791
|
+
(missingTypes) => missingTypes.length > 0 ? report(
|
|
2792
|
+
{
|
|
2793
|
+
node,
|
|
2794
|
+
messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect errors.`,
|
|
2795
|
+
fixes: []
|
|
2796
|
+
}
|
|
2797
|
+
) : void 0
|
|
2798
|
+
),
|
|
2799
|
+
ignore
|
|
2691
2800
|
);
|
|
2692
2801
|
}
|
|
2693
2802
|
}
|
|
@@ -2698,6 +2807,7 @@ var missingEffectError = createDiagnostic({
|
|
|
2698
2807
|
var missingReturnYieldStar = createDiagnostic({
|
|
2699
2808
|
name: "missingReturnYieldStar",
|
|
2700
2809
|
code: 7,
|
|
2810
|
+
severity: "error",
|
|
2701
2811
|
apply: fn("missingReturnYieldStar.apply")(function* (sourceFile, report) {
|
|
2702
2812
|
const ts = yield* service(TypeScriptApi);
|
|
2703
2813
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -2745,7 +2855,6 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
2745
2855
|
}] : [];
|
|
2746
2856
|
report({
|
|
2747
2857
|
node,
|
|
2748
|
-
category: ts.DiagnosticCategory.Error,
|
|
2749
2858
|
messageText: `Yielded Effect never succeeds, so it is best to use a 'return yield*' instead.`,
|
|
2750
2859
|
fixes: fix
|
|
2751
2860
|
});
|
|
@@ -2762,6 +2871,7 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
2762
2871
|
var missingStarInYieldEffectGen = createDiagnostic({
|
|
2763
2872
|
name: "missingStarInYieldEffectGen",
|
|
2764
2873
|
code: 4,
|
|
2874
|
+
severity: "error",
|
|
2765
2875
|
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
2766
2876
|
const ts = yield* service(TypeScriptApi);
|
|
2767
2877
|
const typeParser = yield* service(TypeParser);
|
|
@@ -2801,7 +2911,6 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
2801
2911
|
brokenGenerators.forEach(
|
|
2802
2912
|
(node) => report({
|
|
2803
2913
|
node,
|
|
2804
|
-
category: ts.DiagnosticCategory.Error,
|
|
2805
2914
|
messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
|
|
2806
2915
|
fixes: []
|
|
2807
2916
|
})
|
|
@@ -2824,7 +2933,6 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
2824
2933
|
}] : [];
|
|
2825
2934
|
report({
|
|
2826
2935
|
node,
|
|
2827
|
-
category: ts.DiagnosticCategory.Error,
|
|
2828
2936
|
messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
|
|
2829
2937
|
fixes: fix
|
|
2830
2938
|
});
|
|
@@ -2836,6 +2944,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
2836
2944
|
var returnEffectInGen = createDiagnostic({
|
|
2837
2945
|
name: "returnEffectInGen",
|
|
2838
2946
|
code: 11,
|
|
2947
|
+
severity: "suggestion",
|
|
2839
2948
|
apply: fn("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
2840
2949
|
const ts = yield* service(TypeScriptApi);
|
|
2841
2950
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -2883,7 +2992,6 @@ var returnEffectInGen = createDiagnostic({
|
|
|
2883
2992
|
}] : [];
|
|
2884
2993
|
report({
|
|
2885
2994
|
node,
|
|
2886
|
-
category: ts.DiagnosticCategory.Suggestion,
|
|
2887
2995
|
messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>.
|
|
2888
2996
|
Maybe you wanted to return yield* instead?
|
|
2889
2997
|
Nested Effect-able types may be intended if you plan to later manually flatten or unwrap this Effect, if so you can safely disable this diagnostic for this line through quickfixes.`,
|
|
@@ -2903,6 +3011,7 @@ Nested Effect-able types may be intended if you plan to later manually flatten o
|
|
|
2903
3011
|
var unnecessaryEffectGen = createDiagnostic({
|
|
2904
3012
|
name: "unnecessaryEffectGen",
|
|
2905
3013
|
code: 5,
|
|
3014
|
+
severity: "suggestion",
|
|
2906
3015
|
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
|
|
2907
3016
|
const ts = yield* service(TypeScriptApi);
|
|
2908
3017
|
const typeParser = yield* service(TypeParser);
|
|
@@ -2921,7 +3030,6 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
2921
3030
|
map3(
|
|
2922
3031
|
({ replacementNode }) => report({
|
|
2923
3032
|
node,
|
|
2924
|
-
category: ts.DiagnosticCategory.Suggestion,
|
|
2925
3033
|
messageText: `This Effect.gen contains a single return statement.`,
|
|
2926
3034
|
fixes: [{
|
|
2927
3035
|
fixName: "unnecessaryEffectGen_fix",
|
|
@@ -2946,6 +3054,7 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
2946
3054
|
var unnecessaryPipe = createDiagnostic({
|
|
2947
3055
|
name: "unnecessaryPipe",
|
|
2948
3056
|
code: 9,
|
|
3057
|
+
severity: "suggestion",
|
|
2949
3058
|
apply: fn("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
2950
3059
|
const ts = yield* service(TypeScriptApi);
|
|
2951
3060
|
const typeParser = yield* service(TypeParser);
|
|
@@ -2965,7 +3074,6 @@ var unnecessaryPipe = createDiagnostic({
|
|
|
2965
3074
|
if (args.length === 0) {
|
|
2966
3075
|
report({
|
|
2967
3076
|
node,
|
|
2968
|
-
category: ts.DiagnosticCategory.Suggestion,
|
|
2969
3077
|
messageText: `This pipe call contains no arguments.`,
|
|
2970
3078
|
fixes: [{
|
|
2971
3079
|
fixName: "unnecessaryPipe_fix",
|
|
@@ -2999,7 +3107,8 @@ var diagnostics = [
|
|
|
2999
3107
|
leakingRequirements,
|
|
3000
3108
|
unnecessaryPipe,
|
|
3001
3109
|
genericEffectServices,
|
|
3002
|
-
returnEffectInGen
|
|
3110
|
+
returnEffectInGen,
|
|
3111
|
+
importFromBarrel
|
|
3003
3112
|
];
|
|
3004
3113
|
|
|
3005
3114
|
// src/transform.ts
|