vscode-gem-languageservice 0.0.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/package.json +37 -0
- package/src/index.ts +147 -0
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vscode-gem-languageservice",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Language service for Gem",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"gem",
|
|
7
|
+
"language-service"
|
|
8
|
+
],
|
|
9
|
+
"type": "module",
|
|
10
|
+
"module": "src/index.ts",
|
|
11
|
+
"bin": "src/index.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"/src/"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"gem-analyzer": "^2.2.0",
|
|
18
|
+
"ts-morph": "^13.0.0",
|
|
19
|
+
"typescript": "^5.6.2",
|
|
20
|
+
"vscode-languageserver": "^9.0.1",
|
|
21
|
+
"vscode-languageserver-textdocument": "^1.0.12"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@gemjs/config": "^2.1.0"
|
|
25
|
+
},
|
|
26
|
+
"author": "mantou132",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/mantou132/gem.git",
|
|
31
|
+
"directory": "packages/language-server"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/mantou132/gem/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/mantou132/gem#readme"
|
|
37
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --experimental-transform-types
|
|
2
|
+
import type { Diagnostic, InitializeParams } from 'vscode-languageserver/node';
|
|
3
|
+
import {
|
|
4
|
+
createConnection,
|
|
5
|
+
TextDocuments,
|
|
6
|
+
DiagnosticSeverity,
|
|
7
|
+
ProposedFeatures,
|
|
8
|
+
DidChangeConfigurationNotification,
|
|
9
|
+
CompletionItemKind,
|
|
10
|
+
TextDocumentSyncKind,
|
|
11
|
+
} from 'vscode-languageserver/node';
|
|
12
|
+
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
13
|
+
|
|
14
|
+
const connection = createConnection(ProposedFeatures.all);
|
|
15
|
+
const documents = new TextDocuments(TextDocument);
|
|
16
|
+
|
|
17
|
+
let hasConfigurationCapability = false;
|
|
18
|
+
let hasWorkspaceFolderCapability = false;
|
|
19
|
+
let hasDiagnosticRelatedInformationCapability = false;
|
|
20
|
+
|
|
21
|
+
connection.onInitialize(({ capabilities }: InitializeParams) => {
|
|
22
|
+
hasConfigurationCapability = !!capabilities.workspace?.configuration;
|
|
23
|
+
hasWorkspaceFolderCapability = !!capabilities.workspace?.workspaceFolders;
|
|
24
|
+
hasDiagnosticRelatedInformationCapability = !!capabilities.textDocument?.publishDiagnostics?.relatedInformation;
|
|
25
|
+
return {
|
|
26
|
+
capabilities: {
|
|
27
|
+
textDocumentSync: TextDocumentSyncKind.Incremental,
|
|
28
|
+
completionProvider: { resolveProvider: true },
|
|
29
|
+
workspace: !hasWorkspaceFolderCapability ? undefined : { workspaceFolders: { supported: true } },
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
connection.onInitialized(() => {
|
|
35
|
+
if (hasConfigurationCapability) {
|
|
36
|
+
connection.client.register(DidChangeConfigurationNotification.type, undefined);
|
|
37
|
+
}
|
|
38
|
+
if (hasWorkspaceFolderCapability) {
|
|
39
|
+
connection.workspace.onDidChangeWorkspaceFolders((_event) => {
|
|
40
|
+
connection.console.log('Workspace folder change event received.');
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
interface ExampleSettings {
|
|
46
|
+
maxNumberOfProblems: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const defaultSettings: ExampleSettings = { maxNumberOfProblems: 1000 };
|
|
50
|
+
|
|
51
|
+
let globalSettings: ExampleSettings = defaultSettings;
|
|
52
|
+
const documentSettings: Map<string, Thenable<ExampleSettings>> = new Map();
|
|
53
|
+
|
|
54
|
+
connection.onDidChangeConfiguration((change) => {
|
|
55
|
+
if (hasConfigurationCapability) {
|
|
56
|
+
documentSettings.clear();
|
|
57
|
+
} else {
|
|
58
|
+
globalSettings = <ExampleSettings>(change.settings.languageServerGem || defaultSettings);
|
|
59
|
+
}
|
|
60
|
+
documents.all().forEach(validateTextDocument);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
async function getDocumentSettings(resource: string) {
|
|
64
|
+
if (!hasConfigurationCapability) return globalSettings;
|
|
65
|
+
if (!documentSettings.has(resource)) {
|
|
66
|
+
const settings = connection.workspace.getConfiguration({ scopeUri: resource, section: 'languageServerGem' });
|
|
67
|
+
documentSettings.set(resource, settings);
|
|
68
|
+
}
|
|
69
|
+
return documentSettings.get(resource)!;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
documents.onDidClose((e) => documentSettings.delete(e.document.uri));
|
|
73
|
+
|
|
74
|
+
documents.onDidChangeContent((change) => validateTextDocument(change.document));
|
|
75
|
+
|
|
76
|
+
async function validateTextDocument(textDocument: TextDocument) {
|
|
77
|
+
const settings = await getDocumentSettings(textDocument.uri);
|
|
78
|
+
|
|
79
|
+
const text = textDocument.getText();
|
|
80
|
+
const pattern = /\b[A-Z]{20,}\b/g;
|
|
81
|
+
let m: RegExpExecArray | null;
|
|
82
|
+
|
|
83
|
+
let problems = 0;
|
|
84
|
+
const diagnostics: Diagnostic[] = [];
|
|
85
|
+
while ((m = pattern.exec(text)) && problems < settings.maxNumberOfProblems) {
|
|
86
|
+
problems++;
|
|
87
|
+
const diagnostic: Diagnostic = {
|
|
88
|
+
severity: DiagnosticSeverity.Warning,
|
|
89
|
+
range: { start: textDocument.positionAt(m.index), end: textDocument.positionAt(m.index + m[0].length) },
|
|
90
|
+
message: `${m[0]} is all uppercase.`,
|
|
91
|
+
source: 'vscode-gem',
|
|
92
|
+
};
|
|
93
|
+
if (hasDiagnosticRelatedInformationCapability) {
|
|
94
|
+
diagnostic.relatedInformation = [
|
|
95
|
+
{
|
|
96
|
+
location: {
|
|
97
|
+
uri: textDocument.uri,
|
|
98
|
+
range: Object.assign({}, diagnostic.range),
|
|
99
|
+
},
|
|
100
|
+
message: 'Spelling matters',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
location: {
|
|
104
|
+
uri: textDocument.uri,
|
|
105
|
+
range: Object.assign({}, diagnostic.range),
|
|
106
|
+
},
|
|
107
|
+
message: 'Particularly for names',
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
diagnostics.push(diagnostic);
|
|
112
|
+
}
|
|
113
|
+
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
connection.onDidChangeWatchedFiles((_change) => {
|
|
117
|
+
connection.console.log('We received a file change event');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
connection.onCompletion((_textDocumentPosition) => {
|
|
121
|
+
return [
|
|
122
|
+
{
|
|
123
|
+
label: 'TypeScript',
|
|
124
|
+
kind: CompletionItemKind.Text,
|
|
125
|
+
data: 1,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
label: 'JavaScript',
|
|
129
|
+
kind: CompletionItemKind.Text,
|
|
130
|
+
data: 2,
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
connection.onCompletionResolve((item) => {
|
|
136
|
+
if (item.data === 1) {
|
|
137
|
+
item.detail = 'TypeScript details';
|
|
138
|
+
item.documentation = 'TypeScript documentation';
|
|
139
|
+
} else if (item.data === 2) {
|
|
140
|
+
item.detail = 'JavaScript details';
|
|
141
|
+
item.documentation = 'JavaScript documentation';
|
|
142
|
+
}
|
|
143
|
+
return item;
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
documents.listen(connection);
|
|
147
|
+
connection.listen();
|