elearning/Frontend-Learner/node_modules/@dxup/unimport/dist/index.cjs
2026-01-13 10:48:02 +07:00

144 lines
No EOL
5.4 KiB
JavaScript

//#region ../shared/src/index.ts
function* forEachTouchingNode(ts, sourceFile, position) {
yield* binaryVisit(ts, sourceFile, sourceFile, position);
}
function* binaryVisit(ts, sourceFile, node, position) {
const nodes = [];
ts.forEachChild(node, (child) => {
nodes.push(child);
});
let left = 0;
let right = nodes.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
const node$1 = nodes[mid];
if (position > node$1.getEnd()) left = mid + 1;
else if (position < node$1.getStart(sourceFile)) right = mid - 1;
else {
yield node$1;
yield* binaryVisit(ts, sourceFile, node$1, position);
return;
}
}
}
function isTextSpanWithin(node, textSpan, sourceFile) {
return textSpan.start + textSpan.length <= node.getEnd() && textSpan.start >= node.getStart(sourceFile);
}
//#endregion
//#region src/index.ts
const plugin = (module$1) => {
const { typescript: ts } = module$1;
return { create(info) {
for (const [key, method] of [
["findRenameLocations", findRenameLocations],
["findReferences", findReferences],
["getDefinitionAndBoundSpan", getDefinitionAndBoundSpan]
]) {
const original = info.languageService[key];
info.languageService[key] = method(ts, info, original);
}
return info.languageService;
} };
};
var src_default = plugin;
const declarationRE = /\.d\.(?:c|m)?ts$/;
function createVisitor(getter) {
return (ts, textSpan, sourceFile) => {
for (const node of forEachTouchingNode(ts, sourceFile, textSpan.start)) if (ts.isPropertySignature(node) && node.type || ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.type) {
const target = getter(ts, node.name, node.type, textSpan, sourceFile);
if (target) return target;
}
};
}
const visitForwardImports = createVisitor((ts, name, type, textSpan, sourceFile) => {
if (!isTextSpanWithin(name, textSpan, sourceFile)) return;
while (ts.isTypeReferenceNode(type) && type.typeArguments?.length) type = type.typeArguments[0];
if (ts.isIndexedAccessTypeNode(type)) return type.indexType;
else if (ts.isImportTypeNode(type)) return type.qualifier ?? type.argument;
});
const visitBackwardImports = createVisitor((ts, name, type, textSpan, sourceFile) => {
while (ts.isTypeReferenceNode(type) && type.typeArguments?.length) type = type.typeArguments[0];
let target;
if (ts.isIndexedAccessTypeNode(type)) target = type.indexType;
else if (ts.isImportTypeNode(type)) target = type.qualifier ?? type.argument;
else return;
if (isTextSpanWithin(target, textSpan, sourceFile)) return name;
});
function findRenameLocations(ts, info, findRenameLocations$1) {
return (...args) => {
const result = findRenameLocations$1(...args);
if (!result?.length) return result;
const program = info.languageService.getProgram();
const preferences = typeof args[4] === "object" ? args[4] : {};
const locations = [...result];
for (const location of result) {
const sourceFile = program.getSourceFile(location.fileName);
if (!sourceFile) continue;
if (!declarationRE.test(location.fileName)) continue;
const args$1 = [
ts,
location.textSpan,
sourceFile
];
const node = visitForwardImports(...args$1) ?? visitBackwardImports(...args$1);
if (!node) continue;
const position = node.getStart(sourceFile);
const res = findRenameLocations$1(location.fileName, position, false, false, preferences);
if (res?.length) locations.push(...res);
}
return locations;
};
}
function findReferences(ts, info, findReferences$1) {
return (...args) => {
const result = findReferences$1(...args);
if (!result?.length) return result;
const program = info.languageService.getProgram();
for (const symbol of result) {
const references = new Set(symbol.references);
for (const reference of symbol.references) {
const sourceFile = program.getSourceFile(reference.fileName);
if (!sourceFile) continue;
if (!declarationRE.test(reference.fileName)) continue;
const node = visitBackwardImports(ts, reference.textSpan, sourceFile);
if (!node) continue;
const position = node.getStart(sourceFile) + 1;
const res = info.languageService.getReferencesAtPosition(reference.fileName, position)?.filter((entry) => entry.fileName !== reference.fileName || position < entry.textSpan.start || position > entry.textSpan.start + entry.textSpan.length);
references.delete(reference);
for (const reference$1 of res ?? []) references.add(reference$1);
}
symbol.references = [...references];
}
return result;
};
}
function getDefinitionAndBoundSpan(ts, info, getDefinitionAndBoundSpan$1) {
return (...args) => {
const result = getDefinitionAndBoundSpan$1(...args);
if (!result?.definitions?.length) return result;
const program = info.languageService.getProgram();
const definitions = new Set(result.definitions);
for (const definition of result.definitions) {
const sourceFile = program.getSourceFile(definition.fileName);
if (!sourceFile) continue;
if (!declarationRE.test(definition.fileName)) continue;
const node = visitForwardImports(ts, definition.textSpan, sourceFile);
if (!node) continue;
const position = node.getStart(sourceFile);
const res = getDefinitionAndBoundSpan$1(definition.fileName, position);
if (res?.definitions?.length) {
definitions.delete(definition);
for (const definition$1 of res.definitions) definitions.add(definition$1);
}
}
return {
definitions: [...definitions],
textSpan: result.textSpan
};
};
}
//#endregion
module.exports = src_default;