diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index ca1ba9ff..65f6fa82 100644 --- a/dsymbol/src/dsymbol/modulecache.d +++ b/dsymbol/src/dsymbol/modulecache.d @@ -149,6 +149,8 @@ struct ModuleCache DSymbol* cacheModule(string location) { import std.stdio : File; + import std.path : extension; + import std.process : execute; assert (location !is null); @@ -162,17 +164,39 @@ struct ModuleCache recursionGuard.insert(&cachedLocation.data[0]); - File f = File(cachedLocation); - immutable fileSize = cast(size_t) f.size; - if (fileSize == 0) - return null; + ubyte[] source; + size_t sourceLength; + bool isCFile = cachedLocation.extension == ".c"; - const(Token)[] tokens; - auto parseStringCache = StringCache(fileSize.optimalBucketCount); + if (isCFile) + { + // -o-: do not generate anything + // -Hf=-: print interface file to stdout + // -i: follow imports (druntime's importc module) + auto result = execute(["dmd", "-o-", "-Hf=-", "-i", cachedLocation]); + if (result.status != 0 || result.output.length == 0){ + warning("(importc) failed to generate di for ", location); + return null; + } + sourceLength = result.output.length; + source = cast(ubyte[]) Mallocator.instance.allocate(sourceLength); + source[] = cast(ubyte[]) result.output[]; + } + else { - ubyte[] source = cast(ubyte[]) Mallocator.instance.allocate(fileSize); - scope (exit) Mallocator.instance.deallocate(source); + File f = File(cachedLocation); + sourceLength = cast(size_t) f.size; + if (sourceLength == 0) + return null; + source = cast(ubyte[]) Mallocator.instance.allocate(sourceLength); f.rawRead(source); + } + + scope (exit) Mallocator.instance.deallocate(source); + + const(Token)[] tokens; + auto parseStringCache = StringCache(sourceLength.optimalBucketCount); + { LexerConfig config; config.fileName = cachedLocation; @@ -301,11 +325,17 @@ struct ModuleCache // no exact matches and no .di/package.d matches either else if (!alternative.length) { - string dotDi = buildPath(path, moduleName) ~ ".di"; + string filePath = buildPath(path, moduleName); + string dotDi = filePath ~ ".di"; + string dotC = filePath ~ ".c"; string dotD = dotDi[0 .. $ - 1]; string withoutSuffix = dotDi[0 .. $ - 3]; if (existsAnd!isFile(dotD)) + { return istring(dotD); // return early for exactly matching .d files + } + else if (existsAnd!isFile(dotC)) + return istring(dotC); else if (existsAnd!isFile(dotDi)) alternative = dotDi; else if (existsAnd!isDir(withoutSuffix)) diff --git a/src/dcd/server/autocomplete/complete.d b/src/dcd/server/autocomplete/complete.d index 66228906..3deabc98 100644 --- a/src/dcd/server/autocomplete/complete.d +++ b/src/dcd/server/autocomplete/complete.d @@ -528,8 +528,8 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response, found = true; - auto n = importPath.baseName(".d").baseName(".di"); - if (isFile(importPath) && (importPath.endsWith(".d") || importPath.endsWith(".di")) + auto n = importPath.baseName(".d").baseName(".di").baseName(".c"); + if (isFile(importPath) && (importPath.endsWith(".d") || importPath.endsWith(".di") || importPath.endsWith(".c")) && (partial is null || n.startsWith(partial))) response.completions ~= AutocompleteResponse.Completion(n, CompletionKind.moduleName, null, importPath, 0); } @@ -547,8 +547,8 @@ void setImportCompletions(T)(T tokens, ref AutocompleteResponse response, if (name.baseName.startsWith(".#")) continue; - auto n = name.baseName(".d").baseName(".di"); - if (isFile(name) && (name.endsWith(".d") || name.endsWith(".di")) + auto n = name.baseName(".d").baseName(".di").baseName(".c"); + if (isFile(name) && (name.endsWith(".d") || name.endsWith(".di") || name.endsWith(".c")) && (partial is null || n.startsWith(partial))) response.completions ~= AutocompleteResponse.Completion(n, CompletionKind.moduleName, null, name, 0); else if (isDir(name))