@@ -1583,6 +1583,9 @@ namespace Parser {
1583
1583
// attached to the EOF token.
1584
1584
let parseErrorBeforeNextFinishedNode = false;
1585
1585
1586
+ const tsPlusExternalTypeCache = new Map<string, Record<string, TsPlusTypeDefinition[]>>()
1587
+ const tsPlusResolvedPathsCache = new Map<string, string[]>()
1588
+ const tsPlusResolvedModuleCache = new Map<string, any>()
1586
1589
let currentTsPlusTypes: TsPlusTypeDefinition[] | null = null;
1587
1590
let currentTsPlusFile: string | null = null;
1588
1591
@@ -1821,16 +1824,20 @@ namespace Parser {
1821
1824
}
1822
1825
}
1823
1826
1824
- function parseTsPlusExternalTypes (fileName: string, options: CompilerOptions) {
1827
+ function getTsPlusExternalTypesPaths (fileName: string, options: CompilerOptions) {
1825
1828
if (options.configFilePath) {
1829
+ if (tsPlusResolvedPathsCache.has(options.configFilePath)) {
1830
+ return tsPlusResolvedPathsCache.get(options.configFilePath)!;
1831
+ }
1832
+
1826
1833
let resolvedPaths: string[] = [];
1827
1834
if (options.tsPlusTypes) {
1828
1835
for (const path of options.tsPlusTypes) {
1829
1836
if (pathIsRelative(path)) {
1830
1837
resolvedPaths.push(resolvePath(options.configFilePath.split("/").slice(0, -1).join('/'), path));
1831
1838
}
1832
1839
else {
1833
- const { resolvedModule } = resolveModuleName(path, options.configFilePath, options, sys);
1840
+ const resolvedModule = resolveModuleName(path, options.configFilePath, options, sys).resolvedModule ?? resolveModuleName(path, fileName, options, sys).resolvedModule ;
1834
1841
if (resolvedModule) {
1835
1842
resolvedPaths.push(resolvedModule.resolvedFileName);
1836
1843
break
@@ -1872,22 +1879,37 @@ namespace Parser {
1872
1879
}
1873
1880
}
1874
1881
1875
- if (resolvedPaths.length === 0) {
1876
- return;
1877
- }
1882
+ tsPlusResolvedPathsCache.set(options.configFilePath, resolvedPaths);
1883
+ return resolvedPaths;
1884
+ }
1885
+ return [];
1886
+ }
1878
1887
1879
- for (const resolvedPath of resolvedPaths) {
1888
+ function parseTsPlusExternalTypes(fileName: string, options: CompilerOptions) {
1889
+ const resolvedPaths = getTsPlusExternalTypesPaths(fileName, options);
1890
+ if (!resolvedPaths || resolvedPaths.length === 0) {
1891
+ return
1892
+ }
1893
+ for (const resolvedPath of resolvedPaths) {
1894
+ let json = tsPlusExternalTypeCache.get(resolvedPath);
1895
+ if (!json) {
1880
1896
const text = sys.readFile(resolvedPath);
1881
1897
if (text) {
1882
- const json = JSON.parse(text);
1883
- for (const moduleName in json) {
1884
- const { resolvedModule } = resolveModuleName(moduleName, resolvedPath, options, sys);
1885
- if (resolvedModule && resolvedModule.resolvedFileName === fileName) {
1886
- currentTsPlusTypes = json[moduleName];
1887
- currentTsPlusFile = moduleName;
1888
- return;
1889
- }
1890
- }
1898
+ json = JSON.parse(text);
1899
+ }
1900
+ }
1901
+ if (!json) return;
1902
+ for (const moduleName in json) {
1903
+ const key = `${options.configFilePath ?? fileName}+${moduleName}`;
1904
+ let resolvedModule = tsPlusResolvedModuleCache.get(key);
1905
+ if (!resolvedModule) {
1906
+ resolvedModule = resolveModuleName(moduleName, resolvedPath, options, sys).resolvedModule ?? resolveModuleName(moduleName, fileName, options, sys).resolvedModule;
1907
+ tsPlusResolvedModuleCache.set(key, resolvedModule);
1908
+ }
1909
+ if (resolvedModule && resolvedModule.resolvedFileName === fileName) {
1910
+ currentTsPlusTypes = json[moduleName];
1911
+ currentTsPlusFile = moduleName;
1912
+ return;
1891
1913
}
1892
1914
}
1893
1915
}
@@ -1896,6 +1918,15 @@ namespace Parser {
1896
1918
function addTsPlusTagsFromExternalTypes(declaration: VariableDeclaration | FunctionDeclaration | InterfaceDeclaration | ClassDeclaration | TypeAliasDeclaration, jsDocNode?: HasJSDoc): void {
1897
1919
if (currentTsPlusTypes !== null) {
1898
1920
if (declaration.name && declaration.name.kind === SyntaxKind.Identifier) {
1921
+ if (!jsDocNode) {
1922
+ jsDocNode = declaration;
1923
+ }
1924
+ if (jsDocNode.jsDoc &&
1925
+ jsDocNode.jsDoc[0] &&
1926
+ jsDocNode.jsDoc[0].tags &&
1927
+ jsDocNode.jsDoc[0].tags.find((tag) => tag.tagName.escapedText === 'tsplus')) {
1928
+ return;
1929
+ }
1899
1930
const extensions = currentTsPlusTypes.filter(
1900
1931
(type) =>
1901
1932
(declaration.kind === SyntaxKind.VariableDeclaration ? (type.definitionKind === "const")
@@ -1916,15 +1947,15 @@ namespace Parser {
1916
1947
newTags.push(factory.createJSDocUnknownTag(factory.createIdentifier("tsplus"), comment));
1917
1948
}
1918
1949
newTags.push(factory.createJSDocUnknownTag(factory.createIdentifier("tsplus"), `location "${currentTsPlusFile}"`))
1919
- if (!jsDocNode) {
1920
- jsDocNode = declaration;
1921
- }
1922
1950
if (jsDocNode.jsDoc && jsDocNode.jsDoc[0]) {
1923
- const jsDocTags = factory.createNodeArray( Array.from(jsDocNode.jsDoc[0].tags ?? []).concat(newTags))
1951
+ const jsDocTags = Array.from(jsDocNode.jsDoc[0].tags ?? []).concat(newTags);
1924
1952
// @ts-expect-error
1925
- jsDocNode.jsDoc[0].tags = jsDocTags;
1926
- } else {
1927
- jsDocNode.jsDoc = [factory.createJSDocComment(undefined, newTags)]
1953
+ jsDocNode.jsDoc[0].tags = factory.createNodeArray(jsDocTags);
1954
+ jsDocNode.jsDocCache = jsDocTags;
1955
+ }
1956
+ else {
1957
+ jsDocNode.jsDoc = [factory.createJSDocComment(undefined, newTags)];
1958
+ jsDocNode.jsDocCache = newTags;
1928
1959
}
1929
1960
}
1930
1961
}
@@ -7797,8 +7828,6 @@ namespace Parser {
7797
7828
const pipeableIndexTags: string[] = [];
7798
7829
let isImplicit = false;
7799
7830
7800
- addTsPlusTagsFromExternalTypes(declaration)
7801
-
7802
7831
for (const doc of jsDoc ?? []) {
7803
7832
if (doc.tags) {
7804
7833
for (const tag of doc.tags) {
@@ -7940,6 +7969,7 @@ namespace Parser {
7940
7969
const node = factory.createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body);
7941
7970
(node as Mutable<FunctionDeclaration>).illegalDecorators = decorators;
7942
7971
const finished = withJSDoc(finishNode(node, pos), hasJSDoc);
7972
+ addTsPlusTagsFromExternalTypes(finished);
7943
7973
addTsPlusValueTags(finished, finished.jsDoc);
7944
7974
return finished;
7945
7975
}
0 commit comments