@effect/language-service 0.21.4 → 0.21.6
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/index.js +169 -202
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +169 -202
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -1766,33 +1766,6 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
|
|
|
1766
1766
|
const execute = fn("LSP.ruleExecutor")(function* (rule) {
|
|
1767
1767
|
const ruleNameLowered = rule.name.toLowerCase();
|
|
1768
1768
|
if (skippedRules.indexOf(ruleNameLowered) > -1) return [];
|
|
1769
|
-
let modifiedDiagnostics = yield* rule.apply(sourceFile);
|
|
1770
|
-
const newLevel = pluginOptions.diagnosticSeverity[ruleNameLowered];
|
|
1771
|
-
if (newLevel) {
|
|
1772
|
-
for (const emitted of modifiedDiagnostics) {
|
|
1773
|
-
emitted.category = newLevel && newLevel in levelToDiagnosticCategory ? levelToDiagnosticCategory[newLevel] : emitted.category;
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
for (const emitted of modifiedDiagnostics.slice(0)) {
|
|
1777
|
-
let newLevel2 = void 0;
|
|
1778
|
-
if (!(ruleNameLowered in sectionOverrides || ruleNameLowered in lineOverrides)) continue;
|
|
1779
|
-
const lineOverride = (lineOverrides[ruleNameLowered] || []).find(
|
|
1780
|
-
(_) => _.pos < emitted.node.getStart(sourceFile) && _.end >= emitted.node.getEnd()
|
|
1781
|
-
);
|
|
1782
|
-
if (lineOverride) {
|
|
1783
|
-
newLevel2 = lineOverride.level;
|
|
1784
|
-
} else {
|
|
1785
|
-
const sectionOverride = (sectionOverrides[ruleNameLowered] || []).find(
|
|
1786
|
-
(_) => _.pos < emitted.node.getStart(sourceFile)
|
|
1787
|
-
);
|
|
1788
|
-
if (sectionOverride) newLevel2 = sectionOverride.level;
|
|
1789
|
-
}
|
|
1790
|
-
if (newLevel2 === "off") {
|
|
1791
|
-
modifiedDiagnostics = modifiedDiagnostics.filter((_) => _ !== emitted);
|
|
1792
|
-
} else {
|
|
1793
|
-
emitted.category = newLevel2 && newLevel2 in levelToDiagnosticCategory ? levelToDiagnosticCategory[newLevel2] : emitted.category;
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
1769
|
const fixByDisableNextLine = (_) => ({
|
|
1797
1770
|
fixName: rule.name + "_skipNextLine",
|
|
1798
1771
|
description: "Disable " + rule.name + " for this line",
|
|
@@ -1825,11 +1798,34 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
|
|
|
1825
1798
|
)
|
|
1826
1799
|
)
|
|
1827
1800
|
};
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1801
|
+
let modifiedDiagnostics = [];
|
|
1802
|
+
yield* rule.apply(sourceFile, (entry) => {
|
|
1803
|
+
modifiedDiagnostics.push({
|
|
1804
|
+
...entry,
|
|
1805
|
+
fixes: entry.fixes.concat([fixByDisableNextLine(entry), fixByDisableEntireFile])
|
|
1806
|
+
});
|
|
1807
|
+
});
|
|
1808
|
+
if (!(ruleNameLowered in pluginOptions.diagnosticSeverity || ruleNameLowered in sectionOverrides || ruleNameLowered in lineOverrides)) return modifiedDiagnostics;
|
|
1809
|
+
for (const emitted of modifiedDiagnostics.slice(0)) {
|
|
1810
|
+
let newLevel = pluginOptions.diagnosticSeverity[ruleNameLowered];
|
|
1811
|
+
const lineOverride = (lineOverrides[ruleNameLowered] || []).find(
|
|
1812
|
+
(_) => _.pos < emitted.node.getStart(sourceFile) && _.end >= emitted.node.getEnd()
|
|
1813
|
+
);
|
|
1814
|
+
if (lineOverride) {
|
|
1815
|
+
newLevel = lineOverride.level;
|
|
1816
|
+
} else {
|
|
1817
|
+
const sectionOverride = (sectionOverrides[ruleNameLowered] || []).find(
|
|
1818
|
+
(_) => _.pos < emitted.node.getStart(sourceFile)
|
|
1819
|
+
);
|
|
1820
|
+
if (sectionOverride) newLevel = sectionOverride.level;
|
|
1821
|
+
}
|
|
1822
|
+
if (newLevel === "off") {
|
|
1823
|
+
modifiedDiagnostics = modifiedDiagnostics.filter((_) => _ !== emitted);
|
|
1824
|
+
} else {
|
|
1825
|
+
emitted.category = newLevel && newLevel in levelToDiagnosticCategory ? levelToDiagnosticCategory[newLevel] : emitted.category;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
return modifiedDiagnostics;
|
|
1833
1829
|
});
|
|
1834
1830
|
return { execute };
|
|
1835
1831
|
}
|
|
@@ -2100,6 +2096,16 @@ function make4(ts, typeChecker) {
|
|
|
2100
2096
|
"TypeParser.effectType",
|
|
2101
2097
|
(type) => type
|
|
2102
2098
|
);
|
|
2099
|
+
const strictEffectType = cachedBy(
|
|
2100
|
+
fn("TypeParser.strictEffectType")(function* (type, atLocation) {
|
|
2101
|
+
if (!(type.symbol && type.symbol.name === "Effect" && !type.aliasSymbol)) {
|
|
2102
|
+
return yield* typeParserIssue("Type name should be Effect with no alias symbol", type, atLocation);
|
|
2103
|
+
}
|
|
2104
|
+
return yield* effectType(type, atLocation);
|
|
2105
|
+
}),
|
|
2106
|
+
"TypeParser.strictEffectType",
|
|
2107
|
+
(type) => type
|
|
2108
|
+
);
|
|
2103
2109
|
const layerType = cachedBy(
|
|
2104
2110
|
fn("TypeParser.layerType")(function* (type, atLocation) {
|
|
2105
2111
|
yield* pipeableType(type, atLocation);
|
|
@@ -2451,6 +2457,7 @@ function make4(ts, typeChecker) {
|
|
|
2451
2457
|
);
|
|
2452
2458
|
return {
|
|
2453
2459
|
effectType,
|
|
2460
|
+
strictEffectType,
|
|
2454
2461
|
layerType,
|
|
2455
2462
|
fiberType,
|
|
2456
2463
|
effectSubtype,
|
|
@@ -2537,6 +2544,7 @@ var getMissingTypeEntriesInTargetType = fn(
|
|
|
2537
2544
|
"TypeCheckerApi.getMissingTypeEntriesInTargetType"
|
|
2538
2545
|
)(
|
|
2539
2546
|
function* (realType, expectedType) {
|
|
2547
|
+
if (realType === expectedType) return [];
|
|
2540
2548
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2541
2549
|
const result = [];
|
|
2542
2550
|
let toTest = [realType];
|
|
@@ -2846,12 +2854,11 @@ var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
|
2846
2854
|
var duplicatePackage = createDiagnostic({
|
|
2847
2855
|
name: "duplicatePackage",
|
|
2848
2856
|
code: 6,
|
|
2849
|
-
apply: fn("duplicatePackage.apply")(function* (sourceFile) {
|
|
2857
|
+
apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
2850
2858
|
const ts = yield* service(TypeScriptApi);
|
|
2851
2859
|
const program = yield* service(TypeScriptProgram);
|
|
2852
2860
|
const options = yield* service(LanguageServicePluginOptions);
|
|
2853
|
-
|
|
2854
|
-
if (sourceFile.statements.length < 1) return [];
|
|
2861
|
+
if (sourceFile.statements.length < 1) return;
|
|
2855
2862
|
let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
|
|
2856
2863
|
const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
|
|
2857
2864
|
const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
|
|
@@ -2875,7 +2882,7 @@ var duplicatePackage = createDiagnostic({
|
|
|
2875
2882
|
for (const packageName of Object.keys(resolvedPackages)) {
|
|
2876
2883
|
if (Object.keys(resolvedPackages[packageName]).length > 1) {
|
|
2877
2884
|
const versions = Object.keys(resolvedPackages[packageName]);
|
|
2878
|
-
|
|
2885
|
+
report({
|
|
2879
2886
|
node: sourceFile.statements[0],
|
|
2880
2887
|
category: ts.DiagnosticCategory.Warning,
|
|
2881
2888
|
messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
|
|
@@ -2887,7 +2894,6 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
2887
2894
|
});
|
|
2888
2895
|
}
|
|
2889
2896
|
}
|
|
2890
|
-
return effectDiagnostics;
|
|
2891
2897
|
})
|
|
2892
2898
|
});
|
|
2893
2899
|
|
|
@@ -2895,7 +2901,7 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
2895
2901
|
var floatingEffect = createDiagnostic({
|
|
2896
2902
|
name: "floatingEffect",
|
|
2897
2903
|
code: 3,
|
|
2898
|
-
apply: fn("floatingEffect.apply")(function* (sourceFile) {
|
|
2904
|
+
apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
|
|
2899
2905
|
const ts = yield* service(TypeScriptApi);
|
|
2900
2906
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2901
2907
|
const typeParser = yield* service(TypeParser);
|
|
@@ -2906,7 +2912,6 @@ var floatingEffect = createDiagnostic({
|
|
|
2906
2912
|
if (ts.isBinaryExpression(expression) && expression.operatorToken && (expression.operatorToken.kind === ts.SyntaxKind.EqualsToken || expression.operatorToken.kind === ts.SyntaxKind.QuestionQuestionEqualsToken || expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandEqualsToken || expression.operatorToken.kind === ts.SyntaxKind.BarBarEqualsToken)) return false;
|
|
2907
2913
|
return true;
|
|
2908
2914
|
}
|
|
2909
|
-
const effectDiagnostics = [];
|
|
2910
2915
|
const nodeToVisit = [];
|
|
2911
2916
|
const appendNodeToVisit = (node) => {
|
|
2912
2917
|
nodeToVisit.push(node);
|
|
@@ -2926,7 +2931,7 @@ var floatingEffect = createDiagnostic({
|
|
|
2926
2931
|
option
|
|
2927
2932
|
);
|
|
2928
2933
|
if (isNone2(allowedFloatingEffects)) {
|
|
2929
|
-
|
|
2934
|
+
report({
|
|
2930
2935
|
node,
|
|
2931
2936
|
category: ts.DiagnosticCategory.Error,
|
|
2932
2937
|
messageText: `Effect must be yielded or assigned to a variable.`,
|
|
@@ -2935,7 +2940,6 @@ var floatingEffect = createDiagnostic({
|
|
|
2935
2940
|
}
|
|
2936
2941
|
}
|
|
2937
2942
|
}
|
|
2938
|
-
return effectDiagnostics;
|
|
2939
2943
|
})
|
|
2940
2944
|
});
|
|
2941
2945
|
|
|
@@ -2943,11 +2947,10 @@ var floatingEffect = createDiagnostic({
|
|
|
2943
2947
|
var genericEffectServices = createDiagnostic({
|
|
2944
2948
|
name: "genericEffectServices",
|
|
2945
2949
|
code: 10,
|
|
2946
|
-
apply: fn("genericEffectServices.apply")(function* (sourceFile) {
|
|
2950
|
+
apply: fn("genericEffectServices.apply")(function* (sourceFile, report) {
|
|
2947
2951
|
const ts = yield* service(TypeScriptApi);
|
|
2948
2952
|
const typeParser = yield* service(TypeParser);
|
|
2949
2953
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2950
|
-
const effectDiagnostics = [];
|
|
2951
2954
|
const nodeToVisit = [];
|
|
2952
2955
|
const appendNodeToVisit = (node) => {
|
|
2953
2956
|
nodeToVisit.push(node);
|
|
@@ -2971,7 +2974,7 @@ var genericEffectServices = createDiagnostic({
|
|
|
2971
2974
|
yield* pipe(
|
|
2972
2975
|
typeParser.contextTag(type, node),
|
|
2973
2976
|
map4(() => {
|
|
2974
|
-
|
|
2977
|
+
report({
|
|
2975
2978
|
node: reportAt,
|
|
2976
2979
|
category: ts.DiagnosticCategory.Warning,
|
|
2977
2980
|
messageText: `Effect Services with type parameters are not supported because they cannot be properly discriminated at runtime, which may cause unexpected behavior.`,
|
|
@@ -2983,7 +2986,6 @@ var genericEffectServices = createDiagnostic({
|
|
|
2983
2986
|
);
|
|
2984
2987
|
}
|
|
2985
2988
|
}
|
|
2986
|
-
return effectDiagnostics;
|
|
2987
2989
|
})
|
|
2988
2990
|
});
|
|
2989
2991
|
|
|
@@ -2991,12 +2993,11 @@ var genericEffectServices = createDiagnostic({
|
|
|
2991
2993
|
var leakingRequirements = createDiagnostic({
|
|
2992
2994
|
name: "leakingRequirements",
|
|
2993
2995
|
code: 8,
|
|
2994
|
-
apply: fn("leakingRequirements.apply")(function* (sourceFile) {
|
|
2996
|
+
apply: fn("leakingRequirements.apply")(function* (sourceFile, report) {
|
|
2995
2997
|
const ts = yield* service(TypeScriptApi);
|
|
2996
2998
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
2997
2999
|
const typeParser = yield* service(TypeParser);
|
|
2998
3000
|
const typeOrder = yield* deterministicTypeOrder;
|
|
2999
|
-
const effectDiagnostics = [];
|
|
3000
3001
|
const parseLeakedRequirements = cachedBy(
|
|
3001
3002
|
fn("leakingServices.checkServiceLeaking")(
|
|
3002
3003
|
function* (service2, atLocation) {
|
|
@@ -3047,7 +3048,7 @@ var leakingRequirements = createDiagnostic({
|
|
|
3047
3048
|
);
|
|
3048
3049
|
function reportLeakingRequirements(node, requirements) {
|
|
3049
3050
|
if (requirements.length === 0) return;
|
|
3050
|
-
|
|
3051
|
+
report({
|
|
3051
3052
|
node,
|
|
3052
3053
|
category: ts.DiagnosticCategory.Warning,
|
|
3053
3054
|
messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement`,
|
|
@@ -3089,7 +3090,6 @@ var leakingRequirements = createDiagnostic({
|
|
|
3089
3090
|
);
|
|
3090
3091
|
}
|
|
3091
3092
|
}
|
|
3092
|
-
return effectDiagnostics;
|
|
3093
3093
|
})
|
|
3094
3094
|
});
|
|
3095
3095
|
|
|
@@ -3097,28 +3097,23 @@ var leakingRequirements = createDiagnostic({
|
|
|
3097
3097
|
var missingEffectContext = createDiagnostic({
|
|
3098
3098
|
name: "missingEffectContext",
|
|
3099
3099
|
code: 1,
|
|
3100
|
-
apply: fn("missingEffectContext.apply")(function* (sourceFile) {
|
|
3100
|
+
apply: fn("missingEffectContext.apply")(function* (sourceFile, report) {
|
|
3101
3101
|
const ts = yield* service(TypeScriptApi);
|
|
3102
3102
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3103
3103
|
const typeParser = yield* service(TypeParser);
|
|
3104
3104
|
const typeOrder = yield* deterministicTypeOrder;
|
|
3105
|
-
const checkForMissingContextTypes =
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
)
|
|
3116
|
-
|
|
3117
|
-
realEffect.R,
|
|
3118
|
-
expectedEffect.R
|
|
3119
|
-
);
|
|
3120
|
-
});
|
|
3121
|
-
const effectDiagnostics = [];
|
|
3105
|
+
const checkForMissingContextTypes = (node, expectedType, valueNode, realType) => pipe(
|
|
3106
|
+
all2(
|
|
3107
|
+
typeParser.effectType(expectedType, node),
|
|
3108
|
+
typeParser.effectType(realType, valueNode)
|
|
3109
|
+
),
|
|
3110
|
+
flatMap3(
|
|
3111
|
+
([expectedEffect, realEffect]) => getMissingTypeEntriesInTargetType(
|
|
3112
|
+
realEffect.R,
|
|
3113
|
+
expectedEffect.R
|
|
3114
|
+
)
|
|
3115
|
+
)
|
|
3116
|
+
);
|
|
3122
3117
|
const sortTypes = sort(typeOrder);
|
|
3123
3118
|
const entries = yield* expectedAndRealType(sourceFile);
|
|
3124
3119
|
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
@@ -3132,7 +3127,7 @@ var missingEffectContext = createDiagnostic({
|
|
|
3132
3127
|
orElse3(() => succeed([]))
|
|
3133
3128
|
);
|
|
3134
3129
|
if (missingContext.length > 0) {
|
|
3135
|
-
|
|
3130
|
+
report(
|
|
3136
3131
|
{
|
|
3137
3132
|
node,
|
|
3138
3133
|
category: ts.DiagnosticCategory.Error,
|
|
@@ -3142,7 +3137,6 @@ var missingEffectContext = createDiagnostic({
|
|
|
3142
3137
|
);
|
|
3143
3138
|
}
|
|
3144
3139
|
}
|
|
3145
|
-
return effectDiagnostics;
|
|
3146
3140
|
})
|
|
3147
3141
|
});
|
|
3148
3142
|
|
|
@@ -3150,28 +3144,23 @@ var missingEffectContext = createDiagnostic({
|
|
|
3150
3144
|
var missingEffectError = createDiagnostic({
|
|
3151
3145
|
name: "missingEffectError",
|
|
3152
3146
|
code: 1,
|
|
3153
|
-
apply: fn("missingEffectError.apply")(function* (sourceFile) {
|
|
3147
|
+
apply: fn("missingEffectError.apply")(function* (sourceFile, report) {
|
|
3154
3148
|
const ts = yield* service(TypeScriptApi);
|
|
3155
3149
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3156
3150
|
const typeParser = yield* service(TypeParser);
|
|
3157
3151
|
const typeOrder = yield* deterministicTypeOrder;
|
|
3158
|
-
const checkForMissingErrorTypes =
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
realType,
|
|
3166
|
-
valueNode
|
|
3167
|
-
);
|
|
3168
|
-
return yield* getMissingTypeEntriesInTargetType(
|
|
3152
|
+
const checkForMissingErrorTypes = (node, expectedType, valueNode, realType) => pipe(
|
|
3153
|
+
all2(
|
|
3154
|
+
typeParser.effectType(expectedType, node),
|
|
3155
|
+
typeParser.effectType(realType, valueNode)
|
|
3156
|
+
),
|
|
3157
|
+
flatMap3(
|
|
3158
|
+
([expectedEffect, realEffect]) => getMissingTypeEntriesInTargetType(
|
|
3169
3159
|
realEffect.E,
|
|
3170
3160
|
expectedEffect.E
|
|
3171
|
-
)
|
|
3172
|
-
|
|
3161
|
+
)
|
|
3162
|
+
)
|
|
3173
3163
|
);
|
|
3174
|
-
const effectDiagnostics = [];
|
|
3175
3164
|
const sortTypes = sort(typeOrder);
|
|
3176
3165
|
const entries = yield* expectedAndRealType(sourceFile);
|
|
3177
3166
|
for (const [node, expectedType, valueNode, realType] of entries) {
|
|
@@ -3185,7 +3174,7 @@ var missingEffectError = createDiagnostic({
|
|
|
3185
3174
|
orElse3(() => succeed([]))
|
|
3186
3175
|
);
|
|
3187
3176
|
if (missingContext.length > 0) {
|
|
3188
|
-
|
|
3177
|
+
report(
|
|
3189
3178
|
{
|
|
3190
3179
|
node,
|
|
3191
3180
|
category: ts.DiagnosticCategory.Error,
|
|
@@ -3195,7 +3184,6 @@ var missingEffectError = createDiagnostic({
|
|
|
3195
3184
|
);
|
|
3196
3185
|
}
|
|
3197
3186
|
}
|
|
3198
|
-
return effectDiagnostics;
|
|
3199
3187
|
})
|
|
3200
3188
|
});
|
|
3201
3189
|
|
|
@@ -3203,12 +3191,10 @@ var missingEffectError = createDiagnostic({
|
|
|
3203
3191
|
var missingReturnYieldStar = createDiagnostic({
|
|
3204
3192
|
name: "missingReturnYieldStar",
|
|
3205
3193
|
code: 7,
|
|
3206
|
-
apply: fn("missingReturnYieldStar.apply")(function* (sourceFile) {
|
|
3194
|
+
apply: fn("missingReturnYieldStar.apply")(function* (sourceFile, report) {
|
|
3207
3195
|
const ts = yield* service(TypeScriptApi);
|
|
3208
3196
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3209
3197
|
const typeParser = yield* service(TypeParser);
|
|
3210
|
-
const effectDiagnostics = [];
|
|
3211
|
-
const brokenYields = /* @__PURE__ */ new Set();
|
|
3212
3198
|
const nodeToVisit = [];
|
|
3213
3199
|
const appendNodeToVisit = (node) => {
|
|
3214
3200
|
nodeToVisit.push(node);
|
|
@@ -3236,36 +3222,32 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
3236
3222
|
option
|
|
3237
3223
|
);
|
|
3238
3224
|
if (isSome2(effectGenLike)) {
|
|
3239
|
-
|
|
3225
|
+
const fix = node.expression ? [{
|
|
3226
|
+
fixName: "missingReturnYieldStar_fix",
|
|
3227
|
+
description: "Add return statement",
|
|
3228
|
+
apply: gen2(function* () {
|
|
3229
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
3230
|
+
changeTracker.replaceNode(
|
|
3231
|
+
sourceFile,
|
|
3232
|
+
node,
|
|
3233
|
+
ts.factory.createReturnStatement(
|
|
3234
|
+
node
|
|
3235
|
+
)
|
|
3236
|
+
);
|
|
3237
|
+
})
|
|
3238
|
+
}] : [];
|
|
3239
|
+
report({
|
|
3240
|
+
node,
|
|
3241
|
+
category: ts.DiagnosticCategory.Error,
|
|
3242
|
+
messageText: `Yielded Effect never succeeds, so it is best to use a 'return yield*' instead.`,
|
|
3243
|
+
fixes: fix
|
|
3244
|
+
});
|
|
3240
3245
|
}
|
|
3241
3246
|
}
|
|
3242
3247
|
}
|
|
3243
3248
|
}
|
|
3244
3249
|
}
|
|
3245
3250
|
}
|
|
3246
|
-
brokenYields.forEach((node) => {
|
|
3247
|
-
const fix = node.expression ? [{
|
|
3248
|
-
fixName: "missingReturnYieldStar_fix",
|
|
3249
|
-
description: "Add return statement",
|
|
3250
|
-
apply: gen2(function* () {
|
|
3251
|
-
const changeTracker = yield* service(ChangeTracker);
|
|
3252
|
-
changeTracker.replaceNode(
|
|
3253
|
-
sourceFile,
|
|
3254
|
-
node,
|
|
3255
|
-
ts.factory.createReturnStatement(
|
|
3256
|
-
node
|
|
3257
|
-
)
|
|
3258
|
-
);
|
|
3259
|
-
})
|
|
3260
|
-
}] : [];
|
|
3261
|
-
effectDiagnostics.push({
|
|
3262
|
-
node,
|
|
3263
|
-
category: ts.DiagnosticCategory.Error,
|
|
3264
|
-
messageText: `Yielded Effect never succeeds, so it is best to use a 'return yield*' instead.`,
|
|
3265
|
-
fixes: fix
|
|
3266
|
-
});
|
|
3267
|
-
});
|
|
3268
|
-
return effectDiagnostics;
|
|
3269
3251
|
})
|
|
3270
3252
|
});
|
|
3271
3253
|
|
|
@@ -3273,10 +3255,9 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
3273
3255
|
var missingStarInYieldEffectGen = createDiagnostic({
|
|
3274
3256
|
name: "missingStarInYieldEffectGen",
|
|
3275
3257
|
code: 4,
|
|
3276
|
-
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile) {
|
|
3258
|
+
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
3277
3259
|
const ts = yield* service(TypeScriptApi);
|
|
3278
3260
|
const typeParser = yield* service(TypeParser);
|
|
3279
|
-
const effectDiagnostics = [];
|
|
3280
3261
|
const brokenGenerators = /* @__PURE__ */ new Set();
|
|
3281
3262
|
const brokenYields = /* @__PURE__ */ new Set();
|
|
3282
3263
|
const nodeToVisit = [];
|
|
@@ -3311,7 +3292,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
3311
3292
|
}
|
|
3312
3293
|
}
|
|
3313
3294
|
brokenGenerators.forEach(
|
|
3314
|
-
(node) =>
|
|
3295
|
+
(node) => report({
|
|
3315
3296
|
node,
|
|
3316
3297
|
category: ts.DiagnosticCategory.Error,
|
|
3317
3298
|
messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
|
|
@@ -3334,14 +3315,13 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
3334
3315
|
);
|
|
3335
3316
|
})
|
|
3336
3317
|
}] : [];
|
|
3337
|
-
|
|
3318
|
+
report({
|
|
3338
3319
|
node,
|
|
3339
3320
|
category: ts.DiagnosticCategory.Error,
|
|
3340
3321
|
messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
|
|
3341
3322
|
fixes: fix
|
|
3342
3323
|
});
|
|
3343
3324
|
});
|
|
3344
|
-
return effectDiagnostics;
|
|
3345
3325
|
})
|
|
3346
3326
|
});
|
|
3347
3327
|
|
|
@@ -3349,12 +3329,10 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
3349
3329
|
var returnEffectInGen = createDiagnostic({
|
|
3350
3330
|
name: "returnEffectInGen",
|
|
3351
3331
|
code: 11,
|
|
3352
|
-
apply: fn("returnEffectInGen.apply")(function* (sourceFile) {
|
|
3332
|
+
apply: fn("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
3353
3333
|
const ts = yield* service(TypeScriptApi);
|
|
3354
3334
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3355
3335
|
const typeParser = yield* service(TypeParser);
|
|
3356
|
-
const effectDiagnostics = [];
|
|
3357
|
-
const brokenReturnStatements = /* @__PURE__ */ new Set();
|
|
3358
3336
|
const nodeToVisit = [];
|
|
3359
3337
|
const appendNodeToVisit = (node) => {
|
|
3360
3338
|
nodeToVisit.push(node);
|
|
@@ -3372,48 +3350,43 @@ var returnEffectInGen = createDiagnostic({
|
|
|
3372
3350
|
);
|
|
3373
3351
|
if (!(generatorOrRegularFunction && "asteriskToken" in generatorOrRegularFunction && generatorOrRegularFunction.asteriskToken)) continue;
|
|
3374
3352
|
const type = typeChecker.getTypeAtLocation(node.expression);
|
|
3375
|
-
const maybeEffect = yield* option(typeParser.
|
|
3353
|
+
const maybeEffect = yield* option(typeParser.strictEffectType(type, node.expression));
|
|
3376
3354
|
if (isSome2(maybeEffect)) {
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3355
|
+
if (generatorOrRegularFunction && generatorOrRegularFunction.parent) {
|
|
3356
|
+
const effectGenNode = generatorOrRegularFunction.parent;
|
|
3357
|
+
yield* pipe(
|
|
3358
|
+
typeParser.effectGen(effectGenNode),
|
|
3359
|
+
orElse3(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
3360
|
+
orElse3(() => typeParser.effectFnGen(effectGenNode)),
|
|
3361
|
+
map4(() => {
|
|
3362
|
+
const fix = node.expression ? [{
|
|
3363
|
+
fixName: "returnEffectInGen_fix",
|
|
3364
|
+
description: "Add yield* statement",
|
|
3365
|
+
apply: gen2(function* () {
|
|
3366
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
3367
|
+
changeTracker.replaceNode(
|
|
3368
|
+
sourceFile,
|
|
3369
|
+
node.expression,
|
|
3370
|
+
ts.factory.createYieldExpression(
|
|
3371
|
+
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
3372
|
+
node.expression
|
|
3373
|
+
)
|
|
3374
|
+
);
|
|
3375
|
+
})
|
|
3376
|
+
}] : [];
|
|
3377
|
+
report({
|
|
3378
|
+
node,
|
|
3379
|
+
category: ts.DiagnosticCategory.Suggestion,
|
|
3380
|
+
messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>. Maybe you wanted to return yield* instead? Nested Effect-able types may be intended if you plan to later manually flatten or unwrap this Effect.`,
|
|
3381
|
+
fixes: fix
|
|
3382
|
+
});
|
|
3383
|
+
}),
|
|
3384
|
+
ignore
|
|
3385
|
+
);
|
|
3389
3386
|
}
|
|
3390
3387
|
}
|
|
3391
3388
|
}
|
|
3392
3389
|
}
|
|
3393
|
-
brokenReturnStatements.forEach((node) => {
|
|
3394
|
-
const fix = node.expression ? [{
|
|
3395
|
-
fixName: "returnEffectInGen_fix",
|
|
3396
|
-
description: "Add yield* statement",
|
|
3397
|
-
apply: gen2(function* () {
|
|
3398
|
-
const changeTracker = yield* service(ChangeTracker);
|
|
3399
|
-
changeTracker.replaceNode(
|
|
3400
|
-
sourceFile,
|
|
3401
|
-
node.expression,
|
|
3402
|
-
ts.factory.createYieldExpression(
|
|
3403
|
-
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
3404
|
-
node.expression
|
|
3405
|
-
)
|
|
3406
|
-
);
|
|
3407
|
-
})
|
|
3408
|
-
}] : [];
|
|
3409
|
-
effectDiagnostics.push({
|
|
3410
|
-
node,
|
|
3411
|
-
category: ts.DiagnosticCategory.Suggestion,
|
|
3412
|
-
messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>. Maybe you wanted to return yield* instead? Nested Effect-able types may be intended if you plan to later manually flatten or unwrap this Effect.`,
|
|
3413
|
-
fixes: fix
|
|
3414
|
-
});
|
|
3415
|
-
});
|
|
3416
|
-
return effectDiagnostics;
|
|
3417
3390
|
})
|
|
3418
3391
|
});
|
|
3419
3392
|
|
|
@@ -3421,11 +3394,9 @@ var returnEffectInGen = createDiagnostic({
|
|
|
3421
3394
|
var unnecessaryEffectGen = createDiagnostic({
|
|
3422
3395
|
name: "unnecessaryEffectGen",
|
|
3423
3396
|
code: 5,
|
|
3424
|
-
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile) {
|
|
3397
|
+
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
|
|
3425
3398
|
const ts = yield* service(TypeScriptApi);
|
|
3426
3399
|
const typeParser = yield* service(TypeParser);
|
|
3427
|
-
const effectDiagnostics = [];
|
|
3428
|
-
const unnecessaryGenerators = /* @__PURE__ */ new Map();
|
|
3429
3400
|
const nodeToVisit = [];
|
|
3430
3401
|
const appendNodeToVisit = (node) => {
|
|
3431
3402
|
nodeToVisit.push(node);
|
|
@@ -3438,29 +3409,27 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
3438
3409
|
if (ts.isCallExpression(node)) {
|
|
3439
3410
|
yield* pipe(
|
|
3440
3411
|
typeParser.unnecessaryEffectGen(node),
|
|
3441
|
-
map4(
|
|
3412
|
+
map4(
|
|
3413
|
+
({ replacementNode }) => report({
|
|
3414
|
+
node,
|
|
3415
|
+
category: ts.DiagnosticCategory.Suggestion,
|
|
3416
|
+
messageText: `This Effect.gen contains a single return statement.`,
|
|
3417
|
+
fixes: [{
|
|
3418
|
+
fixName: "unnecessaryEffectGen_fix",
|
|
3419
|
+
description: "Remove the Effect.gen, and keep the body",
|
|
3420
|
+
apply: gen2(function* () {
|
|
3421
|
+
const textChanges = yield* service(
|
|
3422
|
+
ChangeTracker
|
|
3423
|
+
);
|
|
3424
|
+
textChanges.replaceNode(sourceFile, node, yield* replacementNode);
|
|
3425
|
+
})
|
|
3426
|
+
}]
|
|
3427
|
+
})
|
|
3428
|
+
),
|
|
3442
3429
|
ignore
|
|
3443
3430
|
);
|
|
3444
3431
|
}
|
|
3445
3432
|
}
|
|
3446
|
-
unnecessaryGenerators.forEach(
|
|
3447
|
-
(yieldedResult, effectGenCall) => effectDiagnostics.push({
|
|
3448
|
-
node: effectGenCall,
|
|
3449
|
-
category: ts.DiagnosticCategory.Suggestion,
|
|
3450
|
-
messageText: `This Effect.gen contains a single return statement.`,
|
|
3451
|
-
fixes: [{
|
|
3452
|
-
fixName: "unnecessaryEffectGen_fix",
|
|
3453
|
-
description: "Remove the Effect.gen, and keep the body",
|
|
3454
|
-
apply: gen2(function* () {
|
|
3455
|
-
const textChanges = yield* service(
|
|
3456
|
-
ChangeTracker
|
|
3457
|
-
);
|
|
3458
|
-
textChanges.replaceNode(sourceFile, effectGenCall, yield* yieldedResult);
|
|
3459
|
-
})
|
|
3460
|
-
}]
|
|
3461
|
-
})
|
|
3462
|
-
);
|
|
3463
|
-
return effectDiagnostics;
|
|
3464
3433
|
})
|
|
3465
3434
|
});
|
|
3466
3435
|
|
|
@@ -3468,11 +3437,9 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
3468
3437
|
var unnecessaryPipe = createDiagnostic({
|
|
3469
3438
|
name: "unnecessaryPipe",
|
|
3470
3439
|
code: 9,
|
|
3471
|
-
apply: fn("unnecessaryPipe.apply")(function* (sourceFile) {
|
|
3440
|
+
apply: fn("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
3472
3441
|
const ts = yield* service(TypeScriptApi);
|
|
3473
3442
|
const typeParser = yield* service(TypeParser);
|
|
3474
|
-
const pipeDiagnostics = [];
|
|
3475
|
-
const unnecessaryPipes = /* @__PURE__ */ new Map();
|
|
3476
3443
|
const nodeToVisit = [];
|
|
3477
3444
|
const appendNodeToVisit = (node) => {
|
|
3478
3445
|
nodeToVisit.push(node);
|
|
@@ -3485,29 +3452,29 @@ var unnecessaryPipe = createDiagnostic({
|
|
|
3485
3452
|
if (ts.isCallExpression(node)) {
|
|
3486
3453
|
yield* pipe(
|
|
3487
3454
|
typeParser.pipeCall(node),
|
|
3488
|
-
map4(({ args, subject }) =>
|
|
3455
|
+
map4(({ args, subject }) => {
|
|
3456
|
+
if (args.length === 0) {
|
|
3457
|
+
report({
|
|
3458
|
+
node,
|
|
3459
|
+
category: ts.DiagnosticCategory.Suggestion,
|
|
3460
|
+
messageText: `This pipe call contains no arguments.`,
|
|
3461
|
+
fixes: [{
|
|
3462
|
+
fixName: "unnecessaryPipe_fix",
|
|
3463
|
+
description: "Remove the pipe call",
|
|
3464
|
+
apply: gen2(function* () {
|
|
3465
|
+
const textChanges = yield* service(
|
|
3466
|
+
ChangeTracker
|
|
3467
|
+
);
|
|
3468
|
+
textChanges.replaceNode(sourceFile, node, subject);
|
|
3469
|
+
})
|
|
3470
|
+
}]
|
|
3471
|
+
});
|
|
3472
|
+
}
|
|
3473
|
+
}),
|
|
3489
3474
|
ignore
|
|
3490
3475
|
);
|
|
3491
3476
|
}
|
|
3492
3477
|
}
|
|
3493
|
-
unnecessaryPipes.forEach(
|
|
3494
|
-
(pipeCall, pipeSubject) => pipeDiagnostics.push({
|
|
3495
|
-
node: pipeCall,
|
|
3496
|
-
category: ts.DiagnosticCategory.Suggestion,
|
|
3497
|
-
messageText: `This pipe call contains no arguments.`,
|
|
3498
|
-
fixes: [{
|
|
3499
|
-
fixName: "unnecessaryPipe_fix",
|
|
3500
|
-
description: "Remove the pipe call",
|
|
3501
|
-
apply: gen2(function* () {
|
|
3502
|
-
const textChanges = yield* service(
|
|
3503
|
-
ChangeTracker
|
|
3504
|
-
);
|
|
3505
|
-
textChanges.replaceNode(sourceFile, pipeSubject, pipeCall);
|
|
3506
|
-
})
|
|
3507
|
-
}]
|
|
3508
|
-
})
|
|
3509
|
-
);
|
|
3510
|
-
return pipeDiagnostics;
|
|
3511
3478
|
})
|
|
3512
3479
|
});
|
|
3513
3480
|
|