From 28d7dfc131b1f93f8879b3a6ea8c3381fdf9b4a1 Mon Sep 17 00:00:00 2001 From: bangbangsheshotmedown Date: Sat, 28 Feb 2026 16:12:42 +0100 Subject: [PATCH 1/6] Add support for ImportC by turning them to .di on the fly --- dsymbol/src/dsymbol/modulecache.d | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index ca1ba9ff..10e726e6 100644 --- a/dsymbol/src/dsymbol/modulecache.d +++ b/dsymbol/src/dsymbol/modulecache.d @@ -162,10 +162,33 @@ 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"; + + 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 + { + 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); + } const(Token)[] tokens; auto parseStringCache = StringCache(fileSize.optimalBucketCount); From 1e2f6b3fa0e93c976f818fb1d5209d32df05f484 Mon Sep 17 00:00:00 2001 From: bangbangsheshotmedown Date: Sat, 28 Feb 2026 16:18:28 +0100 Subject: [PATCH 2/6] Enable ImportC imports --- dsymbol/src/dsymbol/modulecache.d | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index 10e726e6..062a0d54 100644 --- a/dsymbol/src/dsymbol/modulecache.d +++ b/dsymbol/src/dsymbol/modulecache.d @@ -324,11 +324,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)) From eff6eb0807166db8c8de4d6bb889a0bdd31fc990 Mon Sep 17 00:00:00 2001 From: bangbangsheshotmedown Date: Sat, 28 Feb 2026 16:20:54 +0100 Subject: [PATCH 3/6] Fix build --- dsymbol/src/dsymbol/modulecache.d | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index 062a0d54..bfe45d8a 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); From 89b4edab90e57f45882df88abb892cabba51e6f9 Mon Sep 17 00:00:00 2001 From: bangbangsheshotmedown Date: Sat, 28 Feb 2026 16:32:13 +0100 Subject: [PATCH 4/6] Fix build --- dsymbol/src/dsymbol/modulecache.d | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index bfe45d8a..8c19a976 100644 --- a/dsymbol/src/dsymbol/modulecache.d +++ b/dsymbol/src/dsymbol/modulecache.d @@ -192,12 +192,11 @@ struct ModuleCache f.rawRead(source); } + scope (exit) Mallocator.instance.deallocate(source); + const(Token)[] tokens; auto parseStringCache = StringCache(fileSize.optimalBucketCount); { - ubyte[] source = cast(ubyte[]) Mallocator.instance.allocate(fileSize); - scope (exit) Mallocator.instance.deallocate(source); - f.rawRead(source); LexerConfig config; config.fileName = cachedLocation; From a107b725e6561b9119d336bdb1a2bf6f6a918c46 Mon Sep 17 00:00:00 2001 From: bangbangsheshotmedown Date: Sat, 28 Feb 2026 16:33:43 +0100 Subject: [PATCH 5/6] Fix build --- dsymbol/src/dsymbol/modulecache.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsymbol/src/dsymbol/modulecache.d b/dsymbol/src/dsymbol/modulecache.d index 8c19a976..65f6fa82 100644 --- a/dsymbol/src/dsymbol/modulecache.d +++ b/dsymbol/src/dsymbol/modulecache.d @@ -195,7 +195,7 @@ struct ModuleCache scope (exit) Mallocator.instance.deallocate(source); const(Token)[] tokens; - auto parseStringCache = StringCache(fileSize.optimalBucketCount); + auto parseStringCache = StringCache(sourceLength.optimalBucketCount); { LexerConfig config; config.fileName = cachedLocation; From 7c65fe7edaeb7760cc0f59cd2574b822070b6068 Mon Sep 17 00:00:00 2001 From: bangbangsheshotmedown Date: Sat, 28 Feb 2026 17:09:35 +0100 Subject: [PATCH 6/6] Include c files in import path completions --- src/dcd/server/autocomplete/complete.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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))