@tamagui/language-service 3.0.0-beta.922.1 → 3.0.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/README.md +25 -134
- package/dist/cjs/check.cjs +85 -10
- package/dist/cjs/check.native.cjs +138 -22
- package/dist/cjs/check.native.js +138 -22
- package/dist/cjs/check.native.js.map +1 -1
- package/dist/cjs/core.cjs +8 -4
- package/dist/cjs/core.native.cjs +10 -9
- package/dist/cjs/core.native.js +10 -9
- package/dist/cjs/core.native.js.map +1 -1
- package/dist/cjs/document.cjs +4 -3
- package/dist/cjs/document.native.cjs +5 -3
- package/dist/cjs/document.native.js +5 -3
- package/dist/cjs/document.native.js.map +1 -1
- package/dist/cjs/extract-estree.native.cjs +2 -6
- package/dist/cjs/extract-estree.native.js +2 -6
- package/dist/cjs/extract-estree.native.js.map +1 -1
- package/dist/cjs/index.cjs +5 -284
- package/dist/cjs/index.native.cjs +5 -395
- package/dist/cjs/index.native.js +5 -395
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/check.mjs +87 -12
- package/dist/esm/check.mjs.map +1 -1
- package/dist/esm/check.native.js +140 -24
- package/dist/esm/check.native.js.map +1 -1
- package/dist/esm/core.mjs +8 -4
- package/dist/esm/core.mjs.map +1 -1
- package/dist/esm/core.native.js +10 -9
- package/dist/esm/core.native.js.map +1 -1
- package/dist/esm/document.mjs +4 -3
- package/dist/esm/document.mjs.map +1 -1
- package/dist/esm/document.native.js +5 -3
- package/dist/esm/document.native.js.map +1 -1
- package/dist/esm/extract-estree.native.js +2 -6
- package/dist/esm/extract-estree.native.js.map +1 -1
- package/dist/esm/index.mjs +5 -279
- package/dist/esm/index.native.js +5 -390
- package/package.json +8 -17
- package/src/check.ts +118 -13
- package/src/core.ts +25 -6
- package/src/document.ts +21 -4
- package/src/index.ts +4 -452
- package/types/check.d.ts +4 -0
- package/types/check.d.ts.map +2 -2
- package/types/core.d.ts +7 -2
- package/types/core.d.ts.map +2 -2
- package/types/document.d.ts +8 -2
- package/types/document.d.ts.map +2 -2
- package/types/index.d.ts +4 -7
- package/types/index.d.ts.map +2 -2
- package/dist/cjs/host.cjs +0 -37
- package/dist/cjs/host.native.cjs +0 -60
- package/dist/cjs/host.native.js +0 -62
- package/dist/cjs/host.native.js.map +0 -1
- package/dist/esm/host.mjs +0 -17
- package/dist/esm/host.mjs.map +0 -1
- package/dist/esm/host.native.js +0 -38
- package/dist/esm/host.native.js.map +0 -1
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/index.native.js.map +0 -1
- package/index.cjs +0 -1
- package/src/host.ts +0 -32
- package/types/host.d.ts +0 -10
- package/types/host.d.ts.map +0 -11
package/dist/esm/index.native.js
CHANGED
|
@@ -1,392 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import { completionSortText, createStyleTooling } from "./core.native.js";
|
|
3
|
-
import { resolveTamaguiHost } from "./host.native.js";
|
|
1
|
+
export * from "./core.native.js"
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
var diagnosticCode = 78711;
|
|
7
|
-
var defaultConfigPath = ".tamagui/tamagui.config.json";
|
|
8
|
-
var flatStyledModules = /* @__PURE__ */ new Set([
|
|
9
|
-
"tamagui",
|
|
10
|
-
"tamagui/unstyled",
|
|
11
|
-
"@tamagui/core",
|
|
12
|
-
"@tamagui/ui",
|
|
13
|
-
"@tamagui/web"
|
|
14
|
-
]);
|
|
15
|
-
function loadTooling(info, configPath) {
|
|
16
|
-
var contents = info.serverHost.readFile(configPath);
|
|
17
|
-
if (contents === void 0) return null;
|
|
18
|
-
try {
|
|
19
|
-
return createStyleTooling(JSON.parse(contents));
|
|
20
|
-
} catch (e) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function findStringLiteralAtPosition(typescript, sourceFile, position) {
|
|
25
|
-
var found = null;
|
|
26
|
-
var visit = function(node) {
|
|
27
|
-
if (position < node.getFullStart() || position > node.getEnd()) return;
|
|
28
|
-
if (typescript.isStringLiteralLike(node) && position >= node.getStart(sourceFile) + 1 && position <= node.getEnd() - 1) {
|
|
29
|
-
found = node;
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
typescript.forEachChild(node, visit);
|
|
33
|
-
};
|
|
34
|
-
visit(sourceFile);
|
|
35
|
-
return found;
|
|
36
|
-
}
|
|
37
|
-
function importedBindings(typescript, sourceFile) {
|
|
38
|
-
var styled = /* @__PURE__ */ new Set();
|
|
39
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
40
|
-
try {
|
|
41
|
-
for (var _iterator = sourceFile.statements[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
42
|
-
var statement = _step.value;
|
|
43
|
-
var _statement_importClause;
|
|
44
|
-
if (!typescript.isImportDeclaration(statement) || !typescript.isStringLiteral(statement.moduleSpecifier)) {
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
var source = statement.moduleSpecifier.text;
|
|
48
|
-
if (!flatStyledModules.has(source)) continue;
|
|
49
|
-
var bindings = (_statement_importClause = statement.importClause) === null || _statement_importClause === void 0 ? void 0 : _statement_importClause.namedBindings;
|
|
50
|
-
if (!bindings) continue;
|
|
51
|
-
if (typescript.isNamespaceImport(bindings)) continue;
|
|
52
|
-
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
|
|
53
|
-
try {
|
|
54
|
-
for (var _iterator1 = bindings.elements[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
|
|
55
|
-
var element = _step1.value;
|
|
56
|
-
var _element_propertyName;
|
|
57
|
-
var imported = ((_element_propertyName = element.propertyName) === null || _element_propertyName === void 0 ? void 0 : _element_propertyName.text) || element.name.text;
|
|
58
|
-
if (imported === "styled") styled.add(element.name.text);
|
|
59
|
-
}
|
|
60
|
-
} catch (err) {
|
|
61
|
-
_didIteratorError1 = true;
|
|
62
|
-
_iteratorError1 = err;
|
|
63
|
-
} finally {
|
|
64
|
-
try {
|
|
65
|
-
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
66
|
-
_iterator1.return();
|
|
67
|
-
}
|
|
68
|
-
} finally {
|
|
69
|
-
if (_didIteratorError1) {
|
|
70
|
-
throw _iteratorError1;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} catch (err) {
|
|
76
|
-
_didIteratorError = true;
|
|
77
|
-
_iteratorError = err;
|
|
78
|
-
} finally {
|
|
79
|
-
try {
|
|
80
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
81
|
-
_iterator.return();
|
|
82
|
-
}
|
|
83
|
-
} finally {
|
|
84
|
-
if (_didIteratorError) {
|
|
85
|
-
throw _iteratorError;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return { styled };
|
|
90
|
-
}
|
|
91
|
-
function propertyName(typescript, name) {
|
|
92
|
-
if (typescript.isIdentifier(name) || typescript.isStringLiteral(name)) {
|
|
93
|
-
return name.text;
|
|
94
|
-
}
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
function completionProperty(typescript, literal, tooling, checker, bindings) {
|
|
98
|
-
var parent = literal.parent;
|
|
99
|
-
if (typescript.isJsxExpression(parent)) parent = parent.parent;
|
|
100
|
-
if (typescript.isJsxAttribute(parent)) {
|
|
101
|
-
if (!typescript.isIdentifier(parent.name)) return null;
|
|
102
|
-
var property = parent.name.text;
|
|
103
|
-
if (!tooling.styleProps.has(property)) return null;
|
|
104
|
-
var opening = parent.parent.parent;
|
|
105
|
-
if (!typescript.isJsxOpeningLikeElement(opening)) return null;
|
|
106
|
-
var host = resolveTamaguiHost(checker, opening.tagName);
|
|
107
|
-
if (!(host === null || host === void 0 ? void 0 : host.accepts(property))) return null;
|
|
108
|
-
return { property };
|
|
109
|
-
}
|
|
110
|
-
if (!typescript.isPropertyAssignment(parent)) return null;
|
|
111
|
-
var property1 = propertyName(typescript, parent.name);
|
|
112
|
-
if (!property1 || !tooling.styleProps.has(property1)) return null;
|
|
113
|
-
var current = parent;
|
|
114
|
-
while (current.parent && !typescript.isCallExpression(current.parent)) {
|
|
115
|
-
current = current.parent;
|
|
116
|
-
}
|
|
117
|
-
if (!current.parent || !typescript.isCallExpression(current.parent)) return null;
|
|
118
|
-
var call = current.parent;
|
|
119
|
-
if (call.arguments[1] !== current || !typescript.isIdentifier(call.expression) || !bindings.styled.has(call.expression.text)) {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
var component = call.arguments[0];
|
|
123
|
-
var host1 = component && resolveTamaguiHost(checker, component);
|
|
124
|
-
if (!(host1 === null || host1 === void 0 ? void 0 : host1.accepts(property1))) return null;
|
|
125
|
-
return { property: property1 };
|
|
126
|
-
}
|
|
127
|
-
function siteForLiteral(typescript, sourceFile, literal, tooling, checker, bindings) {
|
|
128
|
-
var site = completionProperty(typescript, literal, tooling, checker, bindings);
|
|
129
|
-
if (!site) return null;
|
|
130
|
-
var contentStart = literal.getStart(sourceFile) + 1;
|
|
131
|
-
var contentEnd = literal.getEnd() - 1;
|
|
132
|
-
var sourceInput = sourceFile.text.slice(contentStart, contentEnd);
|
|
133
|
-
if (literal.text !== sourceInput) return null;
|
|
134
|
-
return {
|
|
135
|
-
property: site.property,
|
|
136
|
-
value: literal.text,
|
|
137
|
-
contentStart,
|
|
138
|
-
literal
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function collectLiteralSites(typescript, sourceFile, tooling, checker, bindings) {
|
|
142
|
-
var sites = [];
|
|
143
|
-
var visit = function(node) {
|
|
144
|
-
if (typescript.isStringLiteralLike(node)) {
|
|
145
|
-
var site = siteForLiteral(typescript, sourceFile, node, tooling, checker, bindings);
|
|
146
|
-
if (site) sites.push(site);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
typescript.forEachChild(node, visit);
|
|
150
|
-
};
|
|
151
|
-
visit(sourceFile);
|
|
152
|
-
return sites;
|
|
153
|
-
}
|
|
154
|
-
function copyLanguageService(service) {
|
|
155
|
-
var proxy = /* @__PURE__ */ Object.create(null);
|
|
156
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
157
|
-
try {
|
|
158
|
-
for (var _iterator = Object.keys(service)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
159
|
-
var key = _step.value;
|
|
160
|
-
var value = service[key];
|
|
161
|
-
proxy[key] = typeof value === "function" ? value.bind(service) : value;
|
|
162
|
-
}
|
|
163
|
-
} catch (err) {
|
|
164
|
-
_didIteratorError = true;
|
|
165
|
-
_iteratorError = err;
|
|
166
|
-
} finally {
|
|
167
|
-
try {
|
|
168
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
169
|
-
_iterator.return();
|
|
170
|
-
}
|
|
171
|
-
} finally {
|
|
172
|
-
if (_didIteratorError) {
|
|
173
|
-
throw _iteratorError;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return proxy;
|
|
178
|
-
}
|
|
179
|
-
var init = function(param) {
|
|
180
|
-
var { typescript } = param;
|
|
181
|
-
return { create(info) {
|
|
182
|
-
var pluginConfig = info.config;
|
|
183
|
-
var configuredPath = (pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig.configPath) || defaultConfigPath;
|
|
184
|
-
var configPath = isAbsolute(configuredPath) ? configuredPath : resolve(info.project.getCurrentDirectory(), configuredPath);
|
|
185
|
-
var tooling = loadTooling(info, configPath);
|
|
186
|
-
var watcher = info.serverHost.watchFile(configPath, function() {
|
|
187
|
-
tooling = loadTooling(info, configPath);
|
|
188
|
-
});
|
|
189
|
-
var proxy = copyLanguageService(info.languageService);
|
|
190
|
-
var baseCompletions = info.languageService.getCompletionsAtPosition.bind(info.languageService);
|
|
191
|
-
var baseDetails = info.languageService.getCompletionEntryDetails.bind(info.languageService);
|
|
192
|
-
var baseSemanticDiagnostics = info.languageService.getSemanticDiagnostics.bind(info.languageService);
|
|
193
|
-
var baseQuickInfo = info.languageService.getQuickInfoAtPosition.bind(info.languageService);
|
|
194
|
-
var baseDispose = info.languageService.dispose.bind(info.languageService);
|
|
195
|
-
var bindingsBySourceFile = /* @__PURE__ */ new WeakMap();
|
|
196
|
-
var fileContext = function(fileName) {
|
|
197
|
-
var program = info.languageService.getProgram();
|
|
198
|
-
var sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(fileName);
|
|
199
|
-
if (!program || !sourceFile) return null;
|
|
200
|
-
var bindings = bindingsBySourceFile.get(sourceFile);
|
|
201
|
-
if (!bindings) {
|
|
202
|
-
bindings = importedBindings(typescript, sourceFile);
|
|
203
|
-
bindingsBySourceFile.set(sourceFile, bindings);
|
|
204
|
-
}
|
|
205
|
-
return {
|
|
206
|
-
sourceFile,
|
|
207
|
-
checker: program.getTypeChecker(),
|
|
208
|
-
bindings
|
|
209
|
-
};
|
|
210
|
-
};
|
|
211
|
-
proxy.getCompletionsAtPosition = function(fileName, position, options, formattingSettings) {
|
|
212
|
-
var getBaseCompletions = function() {
|
|
213
|
-
return baseCompletions(fileName, position, options, formattingSettings);
|
|
214
|
-
};
|
|
215
|
-
if (!tooling) return getBaseCompletions();
|
|
216
|
-
var context = fileContext(fileName);
|
|
217
|
-
if (!context) return getBaseCompletions();
|
|
218
|
-
var { sourceFile, checker, bindings } = context;
|
|
219
|
-
var literal = findStringLiteralAtPosition(typescript, sourceFile, position);
|
|
220
|
-
if (!literal) return getBaseCompletions();
|
|
221
|
-
var site = siteForLiteral(typescript, sourceFile, literal, tooling, checker, bindings);
|
|
222
|
-
if (!site) return getBaseCompletions();
|
|
223
|
-
var cursorCompletions = tooling.completions(site.property, site.value, position - site.contentStart);
|
|
224
|
-
if (!cursorCompletions) return getBaseCompletions();
|
|
225
|
-
var replacementSpan = {
|
|
226
|
-
start: site.contentStart + cursorCompletions.replaceStart,
|
|
227
|
-
length: cursorCompletions.replaceLength
|
|
228
|
-
};
|
|
229
|
-
var entries = [];
|
|
230
|
-
var contextualType;
|
|
231
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
232
|
-
try {
|
|
233
|
-
for (var _iterator = cursorCompletions.completions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
234
|
-
var completion = _step.value;
|
|
235
|
-
var insertText = completion.insertText || completion.value;
|
|
236
|
-
var modifierKind = completion.kind === "modifier" ? tooling.modifierKind(completion.value) : void 0;
|
|
237
|
-
if (completion.kind === "keyword") {
|
|
238
|
-
contextualType || (contextualType = checker.getContextualType(literal));
|
|
239
|
-
if (!contextualType || !checker.isTypeAssignableTo(checker.getStringLiteralType(insertText), contextualType)) {
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
entries.push({
|
|
244
|
-
name: completion.value,
|
|
245
|
-
kind: typescript.ScriptElementKind.string,
|
|
246
|
-
kindModifiers: "",
|
|
247
|
-
sortText: completionSortText(completion, modifierKind),
|
|
248
|
-
insertText,
|
|
249
|
-
replacementSpan,
|
|
250
|
-
source: completionSource,
|
|
251
|
-
labelDetails: { description: modifierKind ? `Tamagui ${modifierKind} modifier` : completion.kind === "configured" ? "Tamagui configured value" : "Tamagui style keyword" }
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
} catch (err) {
|
|
255
|
-
_didIteratorError = true;
|
|
256
|
-
_iteratorError = err;
|
|
257
|
-
} finally {
|
|
258
|
-
try {
|
|
259
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
260
|
-
_iterator.return();
|
|
261
|
-
}
|
|
262
|
-
} finally {
|
|
263
|
-
if (_didIteratorError) {
|
|
264
|
-
throw _iteratorError;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
if (entries.length === 0) return getBaseCompletions();
|
|
269
|
-
return {
|
|
270
|
-
isGlobalCompletion: false,
|
|
271
|
-
isMemberCompletion: false,
|
|
272
|
-
isNewIdentifierLocation: true,
|
|
273
|
-
isIncomplete: true,
|
|
274
|
-
entries
|
|
275
|
-
};
|
|
276
|
-
};
|
|
277
|
-
proxy.getCompletionEntryDetails = function(fileName, position, entryName, formatOptions, source, preferences, data) {
|
|
278
|
-
if (source === completionSource) {
|
|
279
|
-
return {
|
|
280
|
-
name: entryName,
|
|
281
|
-
kind: typescript.ScriptElementKind.string,
|
|
282
|
-
kindModifiers: "",
|
|
283
|
-
displayParts: [{
|
|
284
|
-
text: entryName,
|
|
285
|
-
kind: "stringLiteral"
|
|
286
|
-
}],
|
|
287
|
-
documentation: [{
|
|
288
|
-
text: "Resolved from the active Tamagui config.",
|
|
289
|
-
kind: "text"
|
|
290
|
-
}],
|
|
291
|
-
tags: []
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
return baseDetails(fileName, position, entryName, formatOptions, source, preferences, data);
|
|
295
|
-
};
|
|
296
|
-
proxy.getSemanticDiagnostics = function(fileName) {
|
|
297
|
-
var diagnostics = [...baseSemanticDiagnostics(fileName)];
|
|
298
|
-
if (!tooling) return diagnostics;
|
|
299
|
-
var context = fileContext(fileName);
|
|
300
|
-
if (!context) return diagnostics;
|
|
301
|
-
var { sourceFile, checker, bindings } = context;
|
|
302
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
303
|
-
try {
|
|
304
|
-
for (var _iterator = collectLiteralSites(typescript, sourceFile, tooling, checker, bindings)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
305
|
-
var site = _step.value;
|
|
306
|
-
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
|
|
307
|
-
try {
|
|
308
|
-
for (var _iterator1 = tooling.diagnostics(site.property, site.value)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
|
|
309
|
-
var diagnostic = _step1.value;
|
|
310
|
-
diagnostics.push({
|
|
311
|
-
file: sourceFile,
|
|
312
|
-
start: site.contentStart + diagnostic.start,
|
|
313
|
-
length: Math.max(1, diagnostic.end - diagnostic.start),
|
|
314
|
-
messageText: diagnostic.message,
|
|
315
|
-
category: typescript.DiagnosticCategory.Error,
|
|
316
|
-
code: diagnosticCode,
|
|
317
|
-
source: completionSource
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
} catch (err) {
|
|
321
|
-
_didIteratorError1 = true;
|
|
322
|
-
_iteratorError1 = err;
|
|
323
|
-
} finally {
|
|
324
|
-
try {
|
|
325
|
-
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
326
|
-
_iterator1.return();
|
|
327
|
-
}
|
|
328
|
-
} finally {
|
|
329
|
-
if (_didIteratorError1) {
|
|
330
|
-
throw _iteratorError1;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
} catch (err) {
|
|
336
|
-
_didIteratorError = true;
|
|
337
|
-
_iteratorError = err;
|
|
338
|
-
} finally {
|
|
339
|
-
try {
|
|
340
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
341
|
-
_iterator.return();
|
|
342
|
-
}
|
|
343
|
-
} finally {
|
|
344
|
-
if (_didIteratorError) {
|
|
345
|
-
throw _iteratorError;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
return diagnostics;
|
|
350
|
-
};
|
|
351
|
-
proxy.getQuickInfoAtPosition = function(fileName, position) {
|
|
352
|
-
var getBaseQuickInfo = function() {
|
|
353
|
-
return baseQuickInfo(fileName, position);
|
|
354
|
-
};
|
|
355
|
-
if (!tooling) return getBaseQuickInfo();
|
|
356
|
-
var context = fileContext(fileName);
|
|
357
|
-
if (!context) return getBaseQuickInfo();
|
|
358
|
-
var { sourceFile, checker, bindings } = context;
|
|
359
|
-
var literal = findStringLiteralAtPosition(typescript, sourceFile, position);
|
|
360
|
-
if (!literal) return getBaseQuickInfo();
|
|
361
|
-
var site = siteForLiteral(typescript, sourceFile, literal, tooling, checker, bindings);
|
|
362
|
-
if (!site) return getBaseQuickInfo();
|
|
363
|
-
var hover = tooling.hover(site.property, site.value, position - site.contentStart);
|
|
364
|
-
if (!hover) return getBaseQuickInfo();
|
|
365
|
-
return {
|
|
366
|
-
kind: typescript.ScriptElementKind.string,
|
|
367
|
-
kindModifiers: "",
|
|
368
|
-
textSpan: {
|
|
369
|
-
start: site.contentStart + hover.start,
|
|
370
|
-
length: hover.end - hover.start
|
|
371
|
-
},
|
|
372
|
-
displayParts: [{
|
|
373
|
-
text: hover.text,
|
|
374
|
-
kind: "stringLiteral"
|
|
375
|
-
}],
|
|
376
|
-
documentation: [{
|
|
377
|
-
text: hover.markdown,
|
|
378
|
-
kind: "text"
|
|
379
|
-
}]
|
|
380
|
-
};
|
|
381
|
-
};
|
|
382
|
-
proxy.dispose = function() {
|
|
383
|
-
watcher.close();
|
|
384
|
-
baseDispose();
|
|
385
|
-
};
|
|
386
|
-
return proxy;
|
|
387
|
-
} };
|
|
388
|
-
};
|
|
389
|
-
var index_default = init;
|
|
3
|
+
export * from "./document.native.js"
|
|
390
4
|
|
|
391
|
-
export
|
|
392
|
-
|
|
5
|
+
export * from "./extract-estree.native.js"
|
|
6
|
+
|
|
7
|
+
export * from "./extract-sucrase.native.js"
|
package/package.json
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/language-service",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"source": "src/index.ts",
|
|
8
8
|
"files": [
|
|
9
|
-
"index.cjs",
|
|
10
9
|
"src",
|
|
11
10
|
"types",
|
|
12
11
|
"dist"
|
|
13
12
|
],
|
|
14
|
-
"main": "index.cjs",
|
|
13
|
+
"main": "dist/cjs/index.cjs",
|
|
15
14
|
"module": "dist/esm/index.mjs",
|
|
16
15
|
"types": "types/index.d.ts",
|
|
17
16
|
"exports": {
|
|
18
17
|
"./package.json": "./package.json",
|
|
19
|
-
"./host": {
|
|
20
|
-
"types": "./types/host.d.ts",
|
|
21
|
-
"import": "./dist/esm/host.mjs",
|
|
22
|
-
"default": "./dist/esm/host.mjs"
|
|
23
|
-
},
|
|
24
18
|
"./core": {
|
|
25
19
|
"types": "./types/core.d.ts",
|
|
26
20
|
"import": "./dist/esm/core.mjs",
|
|
@@ -54,7 +48,7 @@
|
|
|
54
48
|
".": {
|
|
55
49
|
"types": "./types/index.d.ts",
|
|
56
50
|
"import": "./dist/esm/index.mjs",
|
|
57
|
-
"require": "./index.cjs",
|
|
51
|
+
"require": "./dist/cjs/index.cjs",
|
|
58
52
|
"default": "./dist/esm/index.mjs"
|
|
59
53
|
}
|
|
60
54
|
},
|
|
@@ -67,22 +61,19 @@
|
|
|
67
61
|
"test:web": "bun run build && vitest --run test"
|
|
68
62
|
},
|
|
69
63
|
"dependencies": {
|
|
70
|
-
"@tamagui/normalize-css-color": "3.0.0
|
|
71
|
-
"@tamagui/style-grammar": "3.0.0
|
|
64
|
+
"@tamagui/normalize-css-color": "3.0.0",
|
|
65
|
+
"@tamagui/style-grammar": "3.0.0",
|
|
72
66
|
"sucrase": "3.35.1"
|
|
73
67
|
},
|
|
74
|
-
"peerDependencies": {
|
|
75
|
-
"typescript": ">=5.7"
|
|
76
|
-
},
|
|
77
68
|
"devDependencies": {
|
|
78
|
-
"@tamagui/build": "3.0.0
|
|
69
|
+
"@tamagui/build": "3.0.0",
|
|
79
70
|
"oxc-parser": "^0.112.0",
|
|
80
|
-
"typescript": "~6.0.3",
|
|
81
71
|
"vitest": "4.1.0"
|
|
82
72
|
},
|
|
83
73
|
"repository": {
|
|
84
74
|
"type": "git",
|
|
85
75
|
"url": "git+https://github.com/tamagui/tamagui.git",
|
|
86
76
|
"directory": "code/core/language-service"
|
|
87
|
-
}
|
|
77
|
+
},
|
|
78
|
+
"releaseSourceCommit": "15fbca480b143f876f6975601e23a17d3f90d2ee"
|
|
88
79
|
}
|
package/src/check.ts
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
// value site with the sucrase tokenizer, and reports the same diagnostics the
|
|
5
5
|
// editor plugin and eslint rule produce, formatted as readable code frames.
|
|
6
6
|
|
|
7
|
-
import { readdirSync, readFileSync } from 'node:fs'
|
|
8
|
-
import { join, relative } from 'node:path'
|
|
7
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
8
|
+
import { dirname, join, relative, resolve } from 'node:path'
|
|
9
|
+
import { spawnSync } from 'node:child_process'
|
|
9
10
|
// deep paths, spelled down to the file: sucrase publishes no `exports` map, and
|
|
10
11
|
// a bare `sucrase/dist/parser` is a directory import that ESM cannot resolve
|
|
11
12
|
import { parse } from 'sucrase/dist/parser/index.js'
|
|
@@ -31,6 +32,13 @@ const skippedDirectories = new Set([
|
|
|
31
32
|
'.expo',
|
|
32
33
|
'.tamagui',
|
|
33
34
|
])
|
|
35
|
+
const projectMarkers = [
|
|
36
|
+
'tamagui.build.ts',
|
|
37
|
+
'tamagui.build.tsx',
|
|
38
|
+
'tamagui.build.js',
|
|
39
|
+
'tamagui.build.mjs',
|
|
40
|
+
'tamagui.build.cjs',
|
|
41
|
+
]
|
|
34
42
|
|
|
35
43
|
export interface CheckStyleFilesOptions {
|
|
36
44
|
/** project root; file discovery and relative display paths anchor here */
|
|
@@ -39,6 +47,8 @@ export interface CheckStyleFilesOptions {
|
|
|
39
47
|
configPath?: string
|
|
40
48
|
/** explicit files to check instead of walking the root */
|
|
41
49
|
files?: readonly string[]
|
|
50
|
+
/** validate clause payloads strictly against token and keyword vocabularies */
|
|
51
|
+
strict?: boolean
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
export interface CheckedFile {
|
|
@@ -52,6 +62,8 @@ export interface CheckStyleFilesResult {
|
|
|
52
62
|
files: readonly CheckedFile[]
|
|
53
63
|
checkedFileCount: number
|
|
54
64
|
diagnosticCount: number
|
|
65
|
+
/** root-relative Tamagui projects omitted because they own another config */
|
|
66
|
+
skippedProjects: readonly string[]
|
|
55
67
|
}
|
|
56
68
|
|
|
57
69
|
export class MissingConfigArtifactError extends Error {
|
|
@@ -63,12 +75,24 @@ export class MissingConfigArtifactError extends Error {
|
|
|
63
75
|
}
|
|
64
76
|
}
|
|
65
77
|
|
|
66
|
-
function walkSourceFiles(
|
|
78
|
+
function walkSourceFiles(
|
|
79
|
+
directory: string,
|
|
80
|
+
root: string,
|
|
81
|
+
results: string[],
|
|
82
|
+
skippedProjects: string[]
|
|
83
|
+
): void {
|
|
67
84
|
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
68
85
|
if (entry.isDirectory()) {
|
|
69
|
-
if (
|
|
70
|
-
|
|
86
|
+
if (skippedDirectories.has(entry.name) || entry.name.startsWith('.')) continue
|
|
87
|
+
const child = join(directory, entry.name)
|
|
88
|
+
if (
|
|
89
|
+
projectMarkers.some((marker) => existsSync(join(child, marker))) ||
|
|
90
|
+
existsSync(join(child, '.tamagui', 'tamagui.config.json'))
|
|
91
|
+
) {
|
|
92
|
+
skippedProjects.push(relative(root, child))
|
|
93
|
+
continue
|
|
71
94
|
}
|
|
95
|
+
walkSourceFiles(child, root, results, skippedProjects)
|
|
72
96
|
continue
|
|
73
97
|
}
|
|
74
98
|
if (sourceExtensions.test(entry.name)) results.push(join(directory, entry.name))
|
|
@@ -82,29 +106,97 @@ export function createProjectExtractor(
|
|
|
82
106
|
}
|
|
83
107
|
|
|
84
108
|
export function checkStyleFiles(options: CheckStyleFilesOptions): CheckStyleFilesResult {
|
|
85
|
-
const
|
|
86
|
-
|
|
109
|
+
const root = resolve(options.root)
|
|
110
|
+
const configPath = options.configPath ?? join(root, '.tamagui', 'tamagui.config.json')
|
|
87
111
|
let contents: string
|
|
88
112
|
try {
|
|
89
113
|
contents = readFileSync(configPath, 'utf8')
|
|
90
114
|
} catch {
|
|
91
115
|
throw new MissingConfigArtifactError(configPath)
|
|
92
116
|
}
|
|
93
|
-
const tooling = createStyleTooling(JSON.parse(contents) as SerializedConfigFile
|
|
117
|
+
const tooling = createStyleTooling(JSON.parse(contents) as SerializedConfigFile, {
|
|
118
|
+
strictPayloads: options.strict,
|
|
119
|
+
})
|
|
94
120
|
if (!tooling) throw new MissingConfigArtifactError(configPath)
|
|
95
121
|
|
|
96
122
|
const document = createDocumentStyleTooling(
|
|
97
123
|
tooling,
|
|
98
|
-
createProjectExtractor((name) => tooling.isStyleProp(name))
|
|
124
|
+
createProjectExtractor((name) => tooling.isStyleProp(name)),
|
|
125
|
+
{ strictPayloads: options.strict }
|
|
99
126
|
)
|
|
100
127
|
|
|
101
128
|
let files: string[]
|
|
129
|
+
const skippedProjects: string[] = []
|
|
102
130
|
if (options.files) {
|
|
103
131
|
files = [...options.files]
|
|
104
132
|
} else {
|
|
105
133
|
files = []
|
|
106
|
-
|
|
134
|
+
const insideGit = spawnSync('git', ['rev-parse', '--is-inside-work-tree'], {
|
|
135
|
+
cwd: root,
|
|
136
|
+
encoding: 'utf8',
|
|
137
|
+
})
|
|
138
|
+
if (insideGit.status === 0) {
|
|
139
|
+
const listed = spawnSync(
|
|
140
|
+
'git',
|
|
141
|
+
[
|
|
142
|
+
'ls-files',
|
|
143
|
+
'--cached',
|
|
144
|
+
'--others',
|
|
145
|
+
'--exclude-standard',
|
|
146
|
+
'-z',
|
|
147
|
+
'--',
|
|
148
|
+
'*.tsx',
|
|
149
|
+
'*.jsx',
|
|
150
|
+
],
|
|
151
|
+
{
|
|
152
|
+
cwd: root,
|
|
153
|
+
encoding: 'utf8',
|
|
154
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
if (listed.error) throw listed.error
|
|
158
|
+
if (listed.status !== 0) {
|
|
159
|
+
throw new Error(listed.stderr.trim() || 'git ls-files failed')
|
|
160
|
+
}
|
|
161
|
+
const skipped = new Set<string>()
|
|
162
|
+
const projectByDirectory = new Map<string, string | null>()
|
|
163
|
+
for (const relativeFile of listed.stdout.split('\0')) {
|
|
164
|
+
if (!relativeFile) continue
|
|
165
|
+
const file = join(root, relativeFile)
|
|
166
|
+
if (!existsSync(file)) continue
|
|
167
|
+
let directory = dirname(file)
|
|
168
|
+
let nestedProject: string | null = null
|
|
169
|
+
const visited: string[] = []
|
|
170
|
+
while (directory !== root) {
|
|
171
|
+
if (projectByDirectory.has(directory)) {
|
|
172
|
+
nestedProject = projectByDirectory.get(directory) ?? null
|
|
173
|
+
break
|
|
174
|
+
}
|
|
175
|
+
visited.push(directory)
|
|
176
|
+
if (
|
|
177
|
+
projectMarkers.some((marker) => existsSync(join(directory, marker))) ||
|
|
178
|
+
existsSync(join(directory, '.tamagui', 'tamagui.config.json'))
|
|
179
|
+
) {
|
|
180
|
+
nestedProject = directory
|
|
181
|
+
break
|
|
182
|
+
}
|
|
183
|
+
directory = dirname(directory)
|
|
184
|
+
}
|
|
185
|
+
for (const visitedDirectory of visited) {
|
|
186
|
+
projectByDirectory.set(visitedDirectory, nestedProject)
|
|
187
|
+
}
|
|
188
|
+
if (nestedProject) {
|
|
189
|
+
skipped.add(relative(root, nestedProject))
|
|
190
|
+
} else {
|
|
191
|
+
files.push(file)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
skippedProjects.push(...skipped)
|
|
195
|
+
} else {
|
|
196
|
+
walkSourceFiles(root, root, files, skippedProjects)
|
|
197
|
+
}
|
|
107
198
|
files.sort()
|
|
199
|
+
skippedProjects.sort()
|
|
108
200
|
}
|
|
109
201
|
|
|
110
202
|
const checked: CheckedFile[] = []
|
|
@@ -118,7 +210,9 @@ export function checkStyleFiles(options: CheckStyleFilesOptions): CheckStyleFile
|
|
|
118
210
|
}
|
|
119
211
|
let diagnostics: readonly DocumentDiagnostic[]
|
|
120
212
|
try {
|
|
121
|
-
diagnostics = document.diagnostics(source
|
|
213
|
+
diagnostics = document.diagnostics(source, undefined, {
|
|
214
|
+
strictPayloads: options.strict,
|
|
215
|
+
})
|
|
122
216
|
} catch {
|
|
123
217
|
// a file sucrase cannot parse is a syntax error the real compiler will
|
|
124
218
|
// report; the style checker stays quiet about it
|
|
@@ -126,10 +220,15 @@ export function checkStyleFiles(options: CheckStyleFilesOptions): CheckStyleFile
|
|
|
126
220
|
}
|
|
127
221
|
if (diagnostics.length === 0) continue
|
|
128
222
|
diagnosticCount += diagnostics.length
|
|
129
|
-
checked.push({ file: relative(
|
|
223
|
+
checked.push({ file: relative(root, file), source, diagnostics })
|
|
130
224
|
}
|
|
131
225
|
|
|
132
|
-
return {
|
|
226
|
+
return {
|
|
227
|
+
files: checked,
|
|
228
|
+
checkedFileCount: files.length,
|
|
229
|
+
diagnosticCount,
|
|
230
|
+
skippedProjects,
|
|
231
|
+
}
|
|
133
232
|
}
|
|
134
233
|
|
|
135
234
|
const ansi = {
|
|
@@ -195,6 +294,12 @@ export function formatCheckResults(
|
|
|
195
294
|
}
|
|
196
295
|
}
|
|
197
296
|
|
|
297
|
+
if (result.skippedProjects.length > 0) {
|
|
298
|
+
output.push(
|
|
299
|
+
paint.dim(`Skipped nested Tamagui projects: ${result.skippedProjects.join(', ')}`)
|
|
300
|
+
)
|
|
301
|
+
}
|
|
302
|
+
|
|
198
303
|
const summary =
|
|
199
304
|
result.diagnosticCount === 0
|
|
200
305
|
? `${paint.bold('✓')} ${result.checkedFileCount} files, no flat value problems`
|