@effect/language-service 0.45.1 → 0.47.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/language-service",
3
- "version": "0.45.1",
3
+ "version": "0.47.0",
4
4
  "description": "A Language-Service Plugin to Refactor and Diagnostic effect-ts projects",
5
5
  "main": "index.cjs",
6
6
  "bin": {
package/transform.js CHANGED
@@ -1160,6 +1160,9 @@ var all = fn("all")(
1160
1160
 
1161
1161
  // src/core/LanguageServicePluginOptions.ts
1162
1162
  var LanguageServicePluginOptions = Tag("PluginOptions");
1163
+ function isValidSeverityLevel(value) {
1164
+ return value === "off" || value === "error" || value === "warning" || value === "message" || value === "suggestion";
1165
+ }
1163
1166
  function parseDiagnosticSeverity(config) {
1164
1167
  if (!isRecord(config)) return {};
1165
1168
  return Object.fromEntries(
@@ -1167,9 +1170,7 @@ function parseDiagnosticSeverity(config) {
1167
1170
  Object.entries(config),
1168
1171
  filter(([key, value]) => isString(key) && isString(value)),
1169
1172
  map3(([key, value]) => [String(key).toLowerCase(), String(value).toLowerCase()]),
1170
- filter(
1171
- ([_, value]) => value === "off" || value === "error" || value === "warning" || value === "message" || value === "suggestion"
1172
- )
1173
+ filter(([_, value]) => isValidSeverityLevel(value))
1173
1174
  )
1174
1175
  );
1175
1176
  }
@@ -1178,6 +1179,7 @@ var defaults = {
1178
1179
  diagnostics: true,
1179
1180
  diagnosticSeverity: {},
1180
1181
  diagnosticsName: true,
1182
+ missingDiagnosticNextLine: "warning",
1181
1183
  quickinfo: true,
1182
1184
  quickinfoEffectParameters: "whentruncated",
1183
1185
  quickinfoMaximumLength: -1,
@@ -1220,6 +1222,7 @@ function parse(config) {
1220
1222
  diagnostics: isObject(config) && hasProperty(config, "diagnostics") && isBoolean(config.diagnostics) ? config.diagnostics : defaults.diagnostics,
1221
1223
  diagnosticSeverity: isObject(config) && hasProperty(config, "diagnosticSeverity") && isRecord(config.diagnosticSeverity) ? parseDiagnosticSeverity(config.diagnosticSeverity) : defaults.diagnosticSeverity,
1222
1224
  diagnosticsName: isObject(config) && hasProperty(config, "diagnosticsName") && isBoolean(config.diagnosticsName) ? config.diagnosticsName : defaults.diagnosticsName,
1225
+ missingDiagnosticNextLine: isObject(config) && hasProperty(config, "missingDiagnosticNextLine") && isString(config.missingDiagnosticNextLine) && isValidSeverityLevel(config.missingDiagnosticNextLine) ? config.missingDiagnosticNextLine : defaults.missingDiagnosticNextLine,
1223
1226
  quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : defaults.quickinfo,
1224
1227
  quickinfoEffectParameters: isObject(config) && hasProperty(config, "quickinfoEffectParameters") && isString(config.quickinfoEffectParameters) && ["always", "never", "whentruncated"].includes(config.quickinfoEffectParameters.toLowerCase()) ? config.quickinfoEffectParameters.toLowerCase() : defaults.quickinfoEffectParameters,
1225
1228
  quickinfoMaximumLength: isObject(config) && hasProperty(config, "quickinfoMaximumLength") && isNumber(config.quickinfoMaximumLength) ? config.quickinfoMaximumLength : defaults.quickinfoMaximumLength,
@@ -1893,7 +1896,8 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1893
1896
  lineOverrides[ruleName].unshift({
1894
1897
  pos: foundNode.node.pos,
1895
1898
  end: foundNode.node.end,
1896
- level: ruleLevel
1899
+ level: ruleLevel,
1900
+ commentRange: foundNode.commentRange
1897
1901
  });
1898
1902
  }
1899
1903
  } else {
@@ -1966,6 +1970,7 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1966
1970
  fixes: entry.fixes.concat(node ? [fixByDisableNextLine(node)] : []).concat([fixByDisableEntireFile])
1967
1971
  });
1968
1972
  });
1973
+ const unusedLineOverrides = new Set(lineOverrides[ruleNameLowered] || []);
1969
1974
  for (const emitted of applicableDiagnostics.slice(0)) {
1970
1975
  let newLevel = defaultLevel;
1971
1976
  const lineOverride = (lineOverrides[ruleNameLowered] || []).find(
@@ -1973,6 +1978,7 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1973
1978
  );
1974
1979
  if (lineOverride) {
1975
1980
  newLevel = lineOverride.level;
1981
+ unusedLineOverrides.delete(lineOverride);
1976
1982
  } else {
1977
1983
  const sectionOverride = (sectionOverrides[ruleNameLowered] || []).find((_) => _.pos < emitted.range.pos);
1978
1984
  if (sectionOverride) newLevel = sectionOverride.level;
@@ -1996,6 +2002,19 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1996
2002
  });
1997
2003
  }
1998
2004
  }
2005
+ if (pluginOptions.missingDiagnosticNextLine !== "off" && unusedLineOverrides.size > 0) {
2006
+ for (const unusedLineOverride of unusedLineOverrides) {
2007
+ diagnostics2.push({
2008
+ file: sourceFile,
2009
+ start: unusedLineOverride.commentRange.pos,
2010
+ length: unusedLineOverride.commentRange.end - unusedLineOverride.commentRange.pos,
2011
+ messageText: `@effect-diagnostics-next-line ${rule.name}:${unusedLineOverride.level} has no effect, make sure you are suppressing the right rule.`,
2012
+ category: levelToDiagnosticCategory[pluginOptions.missingDiagnosticNextLine],
2013
+ code: -1,
2014
+ source: "effect"
2015
+ });
2016
+ }
2017
+ }
1999
2018
  return { diagnostics: diagnostics2, codeFixes };
2000
2019
  });
2001
2020
  return { execute };
@@ -4044,6 +4063,7 @@ var leakingRequirements = createDiagnostic({
4044
4063
  const typeChecker = yield* service(TypeCheckerApi);
4045
4064
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
4046
4065
  const typeParser = yield* service(TypeParser);
4066
+ const tsUtils = yield* service(TypeScriptUtils);
4047
4067
  const parseLeakedRequirements = cachedBy(
4048
4068
  fn("leakingServices.checkServiceLeaking")(
4049
4069
  function* (service2, atLocation) {
@@ -4101,7 +4121,21 @@ var leakingRequirements = createDiagnostic({
4101
4121
  }
4102
4122
  }
4103
4123
  if (sharedRequirementsKeys && sharedRequirementsKeys.length > 0 && effectMembers >= 2) {
4104
- return sharedRequirementsKeys.map((key) => memory.get(key));
4124
+ return sharedRequirementsKeys.map((key) => memory.get(key)).filter(
4125
+ (type) => {
4126
+ let symbol3 = type.symbol;
4127
+ if (symbol3 && symbol3.flags & ts.SymbolFlags.Alias) {
4128
+ symbol3 = typeChecker.getAliasedSymbol(symbol3);
4129
+ }
4130
+ return !(symbol3.declarations || []).some((declaration) => {
4131
+ const declarationSource = tsUtils.getSourceFileOfNode(declaration);
4132
+ if (!declarationSource) return false;
4133
+ return declarationSource.text.substring(declaration.pos, declaration.end).toLowerCase().indexOf(
4134
+ "@effect-leakable-service"
4135
+ ) > -1;
4136
+ });
4137
+ }
4138
+ );
4105
4139
  }
4106
4140
  return [];
4107
4141
  }
@@ -4114,7 +4148,7 @@ var leakingRequirements = createDiagnostic({
4114
4148
  report({
4115
4149
  location: node,
4116
4150
  messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement.
4117
- 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.
4151
+ If these requirements cannot be cached and are expected to be provided per method invocation (e.g. HttpServerRequest), you can either safely disable this diagnostic for this line through quickfixes or mark the service declaration with a JSDoc @effect-leakable-service.
4118
4152
  More info at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
4119
4153
  fixes: []
4120
4154
  });