From abb29d12f30e0652903f4dcffbcf0f484282fed2 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Wed, 19 Oct 2022 18:03:36 +0200 Subject: [PATCH 1/4] add function to resolve paths for a module --- dsymbol/src/dsymbol/modulecache.d | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index ca1ba9ff..e664102d 100644 --- a/dsymbol/src/dsymbol/modulecache.d +++ b/dsymbol/src/dsymbol/modulecache.d @@ -329,6 +329,70 @@ struct ModuleCache return alternative.length > 0 ? istring(alternative) : istring(null); } + /** + * Params: + * moduleName = the name of the module being imported, in "a/b/c" style + * Returns: + * The absolute path to the files that contains the module, or empty if + * not found. + */ + istring[] resolveImportLocations(string moduleName) + { + assert(moduleName !is null, "module name is null"); + if (isRooted(moduleName)) + return [istring(moduleName)]; + + istring[] ret; + + string alternative; + foreach (importPath; importPaths[]) + { + auto path = importPath.path; + // import path is a filename + // first check string if this is a feasable path (no filesystem usage) + if (path.stripExtension.endsWith(moduleName) + && path.existsAnd!isFile) + { + // prefer exact import names above .di/package.d files + ret ~= istring(path); + } + // no exact matches and no .di/package.d matches either + else if (!alternative.length) + { + string dotDi = buildPath(path, moduleName) ~ ".di"; + string dotD = dotDi[0 .. $ - 1]; + string withoutSuffix = dotDi[0 .. $ - 3]; + if (existsAnd!isFile(dotD)) + ret ~= istring(dotD); // return early for exactly matching .d files + else if (existsAnd!isFile(dotDi)) + alternative = dotDi; + else if (existsAnd!isDir(withoutSuffix)) + { + string packagePath = buildPath(withoutSuffix, "package.di"); + if (existsAnd!isFile(packagePath[0 .. $ - 1])) + alternative = packagePath[0 .. $ - 1]; + else if (existsAnd!isFile(packagePath)) + alternative = packagePath; + } + } + // we have a potential .di/package.d file but continue searching for + // exact .d file matches to use instead + else + { + string dotD = buildPath(path, moduleName) ~ ".d"; + if (existsAnd!isFile(dotD)) + ret ~= istring(dotD); // return early for exactly matching .d files + } + } + if (alternative.length > 0) + { + ret ~= istring(alternative); + alternative = ""; + } + + return ret; + } + auto getImportPaths() const { return importPaths[].map!(a => a.path); From 0e27404baf518d4420f3e4edcf8b39b87d727698 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Wed, 19 Oct 2022 18:04:50 +0200 Subject: [PATCH 2/4] include custom object modules --- dsymbol/src/dsymbol/conversion/first.d | 47 ++++++++++++++------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index e4885666..61975460 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -359,28 +359,31 @@ final class FirstPass : ASTVisitor dec.accept(this); } - override void visit(const Module mod) - { - rootSymbol = allocateSemanticSymbol(null, CompletionKind.moduleName, - symbolFile); - currentSymbol = rootSymbol; - moduleScope = GCAllocator.instance.make!Scope(0, uint.max); - currentScope = moduleScope; - auto objectLocation = cache.resolveImportLocation("object"); - if (objectLocation is null) - warning("Could not locate object.d or object.di"); - else - { - auto objectImport = allocateSemanticSymbol(IMPORT_SYMBOL_NAME, - CompletionKind.importSymbol, objectLocation); - objectImport.acSymbol.skipOver = true; - currentSymbol.addChild(objectImport, true); - currentScope.addSymbol(objectImport.acSymbol, false); - } - foreach (s; builtinSymbols[]) - currentScope.addSymbol(s, false); - mod.accept(this); - } + override void visit(const Module mod) + { + rootSymbol = allocateSemanticSymbol(null, CompletionKind.moduleName, + symbolFile); + currentSymbol = rootSymbol; + moduleScope = GCAllocator.instance.make!Scope(0, uint.max); + currentScope = moduleScope; + auto objectLocations = cache.resolveImportLocations("object"); + if (objectLocations is null) + warning("Could not locate object.d or object.di"); + else + { + foreach (objectLocation; objectLocations) + { + auto objectImport = allocateSemanticSymbol(IMPORT_SYMBOL_NAME, + CompletionKind.importSymbol, objectLocation); + objectImport.acSymbol.skipOver = true; + currentSymbol.addChild(objectImport, true); + currentScope.addSymbol(objectImport.acSymbol, false); + } + } + foreach (s; builtinSymbols[]) + currentScope.addSymbol(s, false); + mod.accept(this); + } override void visit(const EnumDeclaration dec) { From 73d8ff66dc381da3abc9bd50984f414eec96b2ba Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Wed, 19 Oct 2022 18:32:33 +0200 Subject: [PATCH 3/4] Avoid GC allocation --- dsymbol/src/dsymbol/modulecache.d | 34 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index e664102d..ede8864b 100644 --- a/dsymbol/src/dsymbol/modulecache.d +++ b/dsymbol/src/dsymbol/modulecache.d @@ -332,18 +332,21 @@ struct ModuleCache /** * Params: * moduleName = the name of the module being imported, in "a/b/c" style + * cb = the callback used to be called whenever a module is found, + * the absolute path is passed as parameter * Returns: - * The absolute path to the files that contains the module, or empty if - * not found. + * The number of resolved paths */ - istring[] resolveImportLocations(string moduleName) + size_t resolveImportLocations(string moduleName, scope void delegate(istring) cb) { assert(moduleName !is null, "module name is null"); if (isRooted(moduleName)) - return [istring(moduleName)]; - - istring[] ret; + { + cb(istring(moduleName)); + return 1; + } + size_t count = 0; string alternative; foreach (importPath; importPaths[]) { @@ -354,7 +357,8 @@ struct ModuleCache && path.existsAnd!isFile) { // prefer exact import names above .di/package.d files - ret ~= istring(path); + cb(istring(path)); + count++; } // no exact matches and no .di/package.d matches either else if (!alternative.length) @@ -363,7 +367,10 @@ struct ModuleCache string dotD = dotDi[0 .. $ - 1]; string withoutSuffix = dotDi[0 .. $ - 3]; if (existsAnd!isFile(dotD)) - ret ~= istring(dotD); // return early for exactly matching .d files + { + cb(istring(dotD)); + count++; + } else if (existsAnd!isFile(dotDi)) alternative = dotDi; else if (existsAnd!isDir(withoutSuffix)) @@ -381,16 +388,19 @@ struct ModuleCache { string dotD = buildPath(path, moduleName) ~ ".d"; if (existsAnd!isFile(dotD)) - ret ~= istring(dotD); // return early for exactly matching .d files + { + cb(istring(dotD)); + count++; + } } } if (alternative.length > 0) { - ret ~= istring(alternative); + cb(istring(alternative)); + count++; alternative = ""; } - - return ret; + return count; } auto getImportPaths() const From a890ece1d0c498787eae41df8394a243b2adc359 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Wed, 19 Oct 2022 18:33:19 +0200 Subject: [PATCH 4/4] Avoid GC allocation --- dsymbol/src/dsymbol/conversion/first.d | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/dsymbol/src/dsymbol/conversion/first.d b/dsymbol/src/dsymbol/conversion/first.d index 61975460..c1e9fce7 100644 --- a/dsymbol/src/dsymbol/conversion/first.d +++ b/dsymbol/src/dsymbol/conversion/first.d @@ -366,20 +366,15 @@ final class FirstPass : ASTVisitor currentSymbol = rootSymbol; moduleScope = GCAllocator.instance.make!Scope(0, uint.max); currentScope = moduleScope; - auto objectLocations = cache.resolveImportLocations("object"); - if (objectLocations is null) - warning("Could not locate object.d or object.di"); - else - { - foreach (objectLocation; objectLocations) - { - auto objectImport = allocateSemanticSymbol(IMPORT_SYMBOL_NAME, - CompletionKind.importSymbol, objectLocation); - objectImport.acSymbol.skipOver = true; - currentSymbol.addChild(objectImport, true); - currentScope.addSymbol(objectImport.acSymbol, false); - } - } + auto numResolved = cache.resolveImportLocations("object", (objectLocation) { + auto objectImport = allocateSemanticSymbol(IMPORT_SYMBOL_NAME, + CompletionKind.importSymbol, objectLocation); + objectImport.acSymbol.skipOver = true; + currentSymbol.addChild(objectImport, true); + currentScope.addSymbol(objectImport.acSymbol, false); + }); + if (numResolved == 0) + warning("Could not locate any object.d or object.di"); foreach (s; builtinSymbols[]) currentScope.addSymbol(s, false); mod.accept(this);