@ripple-ts/language-server 0.2.186 → 0.2.188

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": "@ripple-ts/language-server",
3
- "version": "0.2.186",
3
+ "version": "0.2.188",
4
4
  "description": "Language Server Protocol implementation for Ripple",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -19,10 +19,10 @@
19
19
  "volar-service-typescript": "0.0.65",
20
20
  "vscode-languageserver-textdocument": "^1.0.12",
21
21
  "vscode-uri": "^3.1.0",
22
- "@ripple-ts/typescript-plugin": "0.2.186"
22
+ "@ripple-ts/typescript-plugin": "0.2.188"
23
23
  },
24
24
  "devDependencies": {
25
- "ripple": "0.2.186"
25
+ "ripple": "0.2.188"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "typescript": "^5.9.2"
@@ -1,11 +1,77 @@
1
- /** @import { LanguageServicePlugin } from '@volar/language-server' */
2
- /** @import { LanguageServicePluginInstance } from '@volar/language-server' */
1
+ /**
2
+ @import {
3
+ LanguageServicePlugin,
4
+ LanguageServicePluginInstance,
5
+ LanguageServiceContext,
6
+ Diagnostic,
7
+ } from '@volar/language-server';
8
+ @import {TextDocument} from 'vscode-languageserver-textdocument';
9
+ */
3
10
 
4
11
  const { getVirtualCode, createLogging } = require('./utils.js');
5
12
 
6
13
  const { log, logError } = createLogging('[Ripple TypeScript Diagnostic Plugin]');
7
14
 
8
15
  /**
16
+ * Filter diagnostics based on suppressed diagnostic codes in mappings.
17
+ * @param {TextDocument} document
18
+ * @param {LanguageServiceContext} context
19
+ * @param {Diagnostic[]} diagnostics
20
+ * @returns {Diagnostic[]}
21
+ */
22
+ function filterDiagnostics(document, context, diagnostics) {
23
+ if (!diagnostics || diagnostics.length === 0) {
24
+ return diagnostics;
25
+ }
26
+
27
+ log(`Filtering ${diagnostics.length} TypeScript diagnostics for ${document.uri}`);
28
+
29
+ const [virtualCode] = getVirtualCode(document, context);
30
+
31
+ if (!virtualCode) {
32
+ return diagnostics;
33
+ }
34
+
35
+ const filtered = diagnostics.filter((diagnostic) => {
36
+ const range = diagnostic.range;
37
+ const rangeStart = document.offsetAt(range.start);
38
+ const rangeEnd = document.offsetAt(range.end);
39
+ const mapping = virtualCode.findMappingByGeneratedRange(rangeStart, rangeEnd);
40
+
41
+ if (!mapping) {
42
+ return true;
43
+ }
44
+
45
+ const suppressedCodes = mapping.data.customData?.suppressedDiagnostics;
46
+
47
+ if (!suppressedCodes || suppressedCodes.length === 0) {
48
+ return true;
49
+ }
50
+
51
+ const diagnosticCode =
52
+ typeof diagnostic.code === 'number'
53
+ ? diagnostic.code
54
+ : typeof diagnostic.code === 'string'
55
+ ? parseInt(diagnostic.code)
56
+ : null;
57
+
58
+ if (diagnosticCode && suppressedCodes.includes(diagnosticCode)) {
59
+ log(`Suppressing diagnostic ${diagnosticCode}: ${diagnostic.message}`);
60
+ return false;
61
+ }
62
+
63
+ return true;
64
+ });
65
+
66
+ log(`Filtered from ${diagnostics.length} to ${filtered.length} diagnostics`);
67
+ return filtered;
68
+ }
69
+
70
+ /**
71
+ * Creates a plugin that wraps typescript-semantic's provideDiagnostics
72
+ * to filter out suppressed diagnostics while maintaining the original
73
+ * plugin association. This is crucial for code actions (like "Add import")
74
+ * to work correctly, as volar matches diagnostics by pluginIndex.
9
75
  * @returns {LanguageServicePlugin}
10
76
  */
11
77
  function createTypeScriptDiagnosticFilterPlugin() {
@@ -13,87 +79,42 @@ function createTypeScriptDiagnosticFilterPlugin() {
13
79
 
14
80
  return {
15
81
  name: 'ripple-typescript-diagnostic-filter',
16
- capabilities: {
17
- diagnosticProvider: {
18
- interFileDependencies: false,
19
- workspaceDiagnostics: false,
20
- },
21
- },
82
+ // No capabilities - this plugin only wraps typescript-semantic
83
+ capabilities: {},
22
84
  create(context) {
23
- /** @type {LanguageServicePluginInstance['provideDiagnostics']} */
24
- let originalProvideDiagnostics;
25
- /** @type {LanguageServicePluginInstance} */
85
+ /** @type {LanguageServicePluginInstance['provideDiagnostics'] | undefined} */
86
+ let originalProvider;
87
+ /** @type {LanguageServicePluginInstance | undefined} */
26
88
  let originalInstance;
27
89
 
28
- // Disable typescript-semantic's provideDiagnostics so it doesn't merge with ours
29
90
  for (const [plugin, instance] of context.plugins) {
30
91
  if (plugin.name === 'typescript-semantic') {
31
92
  originalInstance = instance;
32
- originalProvideDiagnostics = instance.provideDiagnostics;
33
- instance.provideDiagnostics = undefined;
93
+ originalProvider = instance.provideDiagnostics;
94
+
95
+ // Wrap the original function to filter diagnostics
96
+ // This maintains the plugin association for code actions
97
+ instance.provideDiagnostics = async function (document, token) {
98
+ const diagnostics = await originalProvider?.call(originalInstance, document, token);
99
+ return filterDiagnostics(document, context, diagnostics ?? []);
100
+ };
101
+
102
+ log('Successfully wrapped typescript-semantic provideDiagnostics');
103
+
34
104
  break;
35
105
  }
36
106
  }
37
107
 
38
- if (!originalProvideDiagnostics) {
108
+ if (!originalProvider) {
39
109
  logError(
40
110
  "'typescript-semantic plugin' was not found or has no 'provideDiagnostics'. \
41
111
  This plugin must be loaded after Volar's typescript-semantic plugin.",
42
112
  );
43
113
  }
44
114
 
45
- return {
46
- async provideDiagnostics(document, token) {
47
- let diagnostics;
48
-
49
- if (originalProvideDiagnostics) {
50
- diagnostics = await originalProvideDiagnostics.call(originalInstance, document, token);
51
- }
52
-
53
- if (!diagnostics || diagnostics.length === 0) {
54
- return diagnostics;
55
- }
56
-
57
- log(`Filtering ${diagnostics.length} TypeScript diagnostics for ${document.uri}`);
58
-
59
- const [virtualCode] = getVirtualCode(document, context);
60
-
61
- const filtered = diagnostics.filter((diagnostic) => {
62
- const range = diagnostic.range;
63
- const rangeStart = document.offsetAt(range.start);
64
- const rangeEnd = document.offsetAt(range.end);
65
- // Get the mapping at this diagnostic position
66
- const mapping = virtualCode.findMappingByGeneratedRange(rangeStart, rangeEnd);
67
-
68
- if (!mapping) {
69
- return true;
70
- }
71
-
72
- const suppressedCodes = mapping.data.customData?.suppressedDiagnostics;
73
-
74
- if (!suppressedCodes || suppressedCodes.length === 0) {
75
- return true;
76
- }
77
-
78
- const diagnosticCode =
79
- typeof diagnostic.code === 'number'
80
- ? diagnostic.code
81
- : typeof diagnostic.code === 'string'
82
- ? parseInt(diagnostic.code)
83
- : null;
84
-
85
- if (diagnosticCode && suppressedCodes.includes(diagnosticCode)) {
86
- log(`Suppressing diagnostic ${diagnosticCode}: ${diagnostic.message}`);
87
- return false; // Filter out this diagnostic
88
- }
89
-
90
- return true; // Keep this diagnostic
91
- });
92
-
93
- log(`Filtered from ${diagnostics.length} to ${filtered.length} diagnostics`);
94
- return filtered;
95
- },
96
- };
115
+ // This plugin doesn't provide any functionality itself,
116
+ // it only wraps typescript-semantic
117
+ return {};
97
118
  },
98
119
  };
99
120
  }