mirror of https://github.com/buggins/dlangide.git
compiler import paths detection - implement #194
This commit is contained in:
parent
37b7eecaf7
commit
9c6a51349b
|
@ -171,52 +171,3 @@ class Builder : BackgroundOperationWatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] splitByLines(string s) {
|
|
||||||
string[] res;
|
|
||||||
int start = 0;
|
|
||||||
for(int i = 0; i <= s.length; i++) {
|
|
||||||
if (i == s.length) {
|
|
||||||
if (start < i)
|
|
||||||
res ~= s[start .. i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (s[i] == '\r' || s[i] == '\n') {
|
|
||||||
if (start < i)
|
|
||||||
res ~= s[start .. i];
|
|
||||||
start = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] detectImportPathsForCompiler(string compiler) {
|
|
||||||
string[] res;
|
|
||||||
import std.process : executeShell;
|
|
||||||
import std.string : startsWith, indexOf;
|
|
||||||
import std.path : buildNormalizedPath;
|
|
||||||
import std.file : write, remove;
|
|
||||||
import dlangui.core.files;
|
|
||||||
try {
|
|
||||||
string sourcefilename = appDataPath(".dlangide") ~ PATH_DELIMITER ~ "tmp_dummy_file_to_get_import_paths.d";
|
|
||||||
write(sourcefilename, "import module_that_does_not_exist;\n");
|
|
||||||
auto ls = executeShell("\"" ~ compiler ~ "\" \"" ~ sourcefilename ~ "\"");
|
|
||||||
remove(sourcefilename);
|
|
||||||
string s = ls.output;
|
|
||||||
string[] lines = splitByLines(s);
|
|
||||||
debug Log.d("compiler output:\n", s);
|
|
||||||
foreach(line; lines) {
|
|
||||||
if (line.startsWith("import path[")) {
|
|
||||||
auto p = line.indexOf("] = ");
|
|
||||||
if (p > 0) {
|
|
||||||
line = line[p + 4 .. $];
|
|
||||||
string path = line.buildNormalizedPath;
|
|
||||||
debug Log.d("import path found: `", line, "`");
|
|
||||||
res ~= line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class DEditorTool : EditorTool
|
||||||
DCDTask _getDocCommentsTask;
|
DCDTask _getDocCommentsTask;
|
||||||
override void getDocComments(DSourceEdit editor, TextPosition caretPosition, void delegate(string[]) callback) {
|
override void getDocComments(DSourceEdit editor, TextPosition caretPosition, void delegate(string[]) callback) {
|
||||||
cancelGetDocComments();
|
cancelGetDocComments();
|
||||||
string[] importPaths = editor.importPaths();
|
string[] importPaths = editor.importPaths(_frame.settings);
|
||||||
string content = toUTF8(editor.text);
|
string content = toUTF8(editor.text);
|
||||||
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
||||||
if (!isAtWord(content, byteOffset))
|
if (!isAtWord(content, byteOffset))
|
||||||
|
@ -88,7 +88,7 @@ class DEditorTool : EditorTool
|
||||||
DCDTask _goToDefinitionTask;
|
DCDTask _goToDefinitionTask;
|
||||||
override void goToDefinition(DSourceEdit editor, TextPosition caretPosition) {
|
override void goToDefinition(DSourceEdit editor, TextPosition caretPosition) {
|
||||||
cancelGoToDefinition();
|
cancelGoToDefinition();
|
||||||
string[] importPaths = editor.importPaths();
|
string[] importPaths = editor.importPaths(_frame.settings);
|
||||||
string content = toUTF8(editor.text);
|
string content = toUTF8(editor.text);
|
||||||
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ class DEditorTool : EditorTool
|
||||||
DCDTask _getCompletionsTask;
|
DCDTask _getCompletionsTask;
|
||||||
override void getCompletions(DSourceEdit editor, TextPosition caretPosition, void delegate(dstring[] completions, string[] icons, CompletionTypes type) callback) {
|
override void getCompletions(DSourceEdit editor, TextPosition caretPosition, void delegate(dstring[] completions, string[] icons, CompletionTypes type) callback) {
|
||||||
cancelGetCompletions();
|
cancelGetCompletions();
|
||||||
string[] importPaths = editor.importPaths();
|
string[] importPaths = editor.importPaths(_frame.settings);
|
||||||
|
|
||||||
string content = toUTF8(editor.text);
|
string content = toUTF8(editor.text);
|
||||||
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
||||||
|
|
|
@ -214,9 +214,9 @@ class DSourceEdit : SourceEdit, EditableContentMarksChangeListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns project import paths - if file from project is opened in current editor
|
/// returns project import paths - if file from project is opened in current editor
|
||||||
string[] importPaths() {
|
string[] importPaths(IDESettings ideSettings) {
|
||||||
if (_projectSourceFile)
|
if (_projectSourceFile)
|
||||||
return _projectSourceFile.project.importPaths;
|
return _projectSourceFile.project.importPaths(ideSettings);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -698,20 +698,20 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL
|
||||||
_logPanel.appendText(null, dubPath ? ("dub path: "d ~ toUTF32(dubPath) ~ "\n"d) : ("dub is not found! cannot build projects without DUB\n"d));
|
_logPanel.appendText(null, dubPath ? ("dub path: "d ~ toUTF32(dubPath) ~ "\n"d) : ("dub is not found! cannot build projects without DUB\n"d));
|
||||||
_logPanel.appendText(null, rdmdPath ? ("rdmd path: "d ~ toUTF32(rdmdPath) ~ "\n"d) : ("rdmd is not found!\n"d));
|
_logPanel.appendText(null, rdmdPath ? ("rdmd path: "d ~ toUTF32(rdmdPath) ~ "\n"d) : ("rdmd is not found!\n"d));
|
||||||
_logPanel.appendText(null, dmdPath ? ("dmd path: "d ~ toUTF32(dmdPath) ~ "\n"d) : ("dmd compiler is not found!\n"d));
|
_logPanel.appendText(null, dmdPath ? ("dmd path: "d ~ toUTF32(dmdPath) ~ "\n"d) : ("dmd compiler is not found!\n"d));
|
||||||
dumpCompilerPath("DMD", dmdPath);
|
dumpCompilerPath("dmd", dmdPath);
|
||||||
_logPanel.appendText(null, ldcPath ? ("ldc path: "d ~ toUTF32(ldcPath) ~ "\n"d) : ("ldc compiler is not found!\n"d));
|
_logPanel.appendText(null, ldcPath ? ("ldc path: "d ~ toUTF32(ldcPath) ~ "\n"d) : ("ldc compiler is not found!\n"d));
|
||||||
dumpCompilerPath("LDC", ldcPath);
|
dumpCompilerPath("ldc", ldcPath);
|
||||||
_logPanel.appendText(null, gdcPath ? ("gdc path: "d ~ toUTF32(gdcPath) ~ "\n"d) : ("gdc compiler is not found!\n"d));
|
_logPanel.appendText(null, gdcPath ? ("gdc path: "d ~ toUTF32(gdcPath) ~ "\n"d) : ("gdc compiler is not found!\n"d));
|
||||||
dumpCompilerPath("GDC", gdcPath);
|
dumpCompilerPath("gdc", gdcPath);
|
||||||
}
|
}
|
||||||
private void dumpCompilerPath(dstring compilerName, string compiler) {
|
private void dumpCompilerPath(string compilerName, string compiler) {
|
||||||
if (!compiler)
|
if (!compiler)
|
||||||
return;
|
return;
|
||||||
if (compiler) {
|
if (compiler) {
|
||||||
string[] imports = detectImportPathsForCompiler(compiler);
|
string[] imports = compilerImportPathsCache.getImportPathsFor(compilerName);
|
||||||
if (imports.length > 0) {
|
if (imports.length > 0) {
|
||||||
Log.d(compilerName, " imports:", imports);
|
Log.d(compilerName, " imports:", imports);
|
||||||
_logPanel.appendText(null, compilerName ~ " imports:\n"d);
|
_logPanel.appendText(null, to!dstring(compilerName) ~ " imports:\n"d);
|
||||||
foreach(s; imports)
|
foreach(s; imports)
|
||||||
_logPanel.appendText(null, " "d ~ to!dstring(s) ~ "\n"d);
|
_logPanel.appendText(null, " "d ~ to!dstring(s) ~ "\n"d);
|
||||||
}
|
}
|
||||||
|
@ -1601,7 +1601,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL
|
||||||
}
|
}
|
||||||
|
|
||||||
public void warmUpImportPaths(Project project) {
|
public void warmUpImportPaths(Project project) {
|
||||||
dcdInterface.warmUp(project.importPaths);
|
dcdInterface.warmUp(project.importPaths(_settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
void restoreListOfOpenedFiles() {
|
void restoreListOfOpenedFiles() {
|
||||||
|
|
|
@ -305,29 +305,6 @@ class WorkspaceItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// detect DMD source paths
|
|
||||||
string[] dmdSourcePaths() {
|
|
||||||
string[] res;
|
|
||||||
|
|
||||||
if(!includePath.empty){
|
|
||||||
res ~= includePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
version(Windows) {
|
|
||||||
import dlangui.core.files;
|
|
||||||
string dmdPath = findExecutablePath("dmd");
|
|
||||||
if (dmdPath) {
|
|
||||||
string dmdDir = buildNormalizedPath(dirName(dmdPath), "..", "..", "src");
|
|
||||||
res ~= absolutePath(buildNormalizedPath(dmdDir, "druntime", "import"));
|
|
||||||
res ~= absolutePath(buildNormalizedPath(dmdDir, "phobos"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res ~= "/usr/include/dmd/druntime/import";
|
|
||||||
res ~= "/usr/include/dmd/phobos";
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stores info about project configuration
|
/// Stores info about project configuration
|
||||||
struct ProjectConfiguration {
|
struct ProjectConfiguration {
|
||||||
/// name used to build the project
|
/// name used to build the project
|
||||||
|
@ -384,6 +361,7 @@ struct ProjectConfiguration {
|
||||||
|
|
||||||
/// DLANGIDE D project
|
/// DLANGIDE D project
|
||||||
class Project : WorkspaceItem {
|
class Project : WorkspaceItem {
|
||||||
|
import dlangide.workspace.idesettings : IDESettings;
|
||||||
protected Workspace _workspace;
|
protected Workspace _workspace;
|
||||||
protected bool _opened;
|
protected bool _opened;
|
||||||
protected ProjectFolder _items;
|
protected ProjectFolder _items;
|
||||||
|
@ -397,7 +375,6 @@ class Project : WorkspaceItem {
|
||||||
protected string _dependencyVersion;
|
protected string _dependencyVersion;
|
||||||
|
|
||||||
protected string[] _sourcePaths;
|
protected string[] _sourcePaths;
|
||||||
protected string[] _builderSourcePaths;
|
|
||||||
protected ProjectConfiguration[] _configurations;
|
protected ProjectConfiguration[] _configurations;
|
||||||
protected ProjectConfiguration _projectConfiguration = ProjectConfiguration.DEFAULT;
|
protected ProjectConfiguration _projectConfiguration = ProjectConfiguration.DEFAULT;
|
||||||
|
|
||||||
|
@ -529,12 +506,12 @@ class Project : WorkspaceItem {
|
||||||
|
|
||||||
/// returns project's own source paths
|
/// returns project's own source paths
|
||||||
@property string[] sourcePaths() { return _sourcePaths; }
|
@property string[] sourcePaths() { return _sourcePaths; }
|
||||||
/// returns project's own source paths
|
/// returns project's current toolchain import paths
|
||||||
@property string[] builderSourcePaths() {
|
string[] builderSourcePaths(IDESettings ideSettings) {
|
||||||
if (!_builderSourcePaths) {
|
string compilerName = settings.getToolchain(ideSettings);
|
||||||
_builderSourcePaths = dmdSourcePaths();
|
if (!compilerName)
|
||||||
}
|
compilerName = "default";
|
||||||
return _builderSourcePaths;
|
return compilerImportPathsCache.getImportPathsFor(compilerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns first source folder for project or null if not found
|
/// returns first source folder for project or null if not found
|
||||||
|
@ -556,10 +533,10 @@ class Project : WorkspaceItem {
|
||||||
dst ~= item;
|
dst ~= item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@property string[] importPaths() {
|
@property string[] importPaths(IDESettings ideSettings) {
|
||||||
string[] res;
|
string[] res;
|
||||||
addUnique(res, sourcePaths);
|
addUnique(res, sourcePaths);
|
||||||
addUnique(res, builderSourcePaths);
|
addUnique(res, builderSourcePaths(ideSettings));
|
||||||
foreach(dep; _dependencies) {
|
foreach(dep; _dependencies) {
|
||||||
addUnique(res, dep.sourcePaths);
|
addUnique(res, dep.sourcePaths);
|
||||||
}
|
}
|
||||||
|
@ -805,7 +782,7 @@ class Project : WorkspaceItem {
|
||||||
findMainSourceFile();
|
findMainSourceFile();
|
||||||
|
|
||||||
Log.i("Project source paths: ", sourcePaths);
|
Log.i("Project source paths: ", sourcePaths);
|
||||||
Log.i("Builder source paths: ", builderSourcePaths);
|
//Log.i("Builder source paths: ", builderSourcePaths(_settings));
|
||||||
if (!_isDependency)
|
if (!_isDependency)
|
||||||
loadSelections();
|
loadSelections();
|
||||||
|
|
||||||
|
@ -1003,3 +980,99 @@ class EditorBookmark {
|
||||||
int line;
|
int line;
|
||||||
string projectName;
|
string projectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string[] splitByLines(string s) {
|
||||||
|
string[] res;
|
||||||
|
int start = 0;
|
||||||
|
for(int i = 0; i <= s.length; i++) {
|
||||||
|
if (i == s.length) {
|
||||||
|
if (start < i)
|
||||||
|
res ~= s[start .. i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (s[i] == '\r' || s[i] == '\n') {
|
||||||
|
if (start < i)
|
||||||
|
res ~= s[start .. i];
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CompilerImportPathsCache {
|
||||||
|
|
||||||
|
private static class Entry {
|
||||||
|
string[] list;
|
||||||
|
}
|
||||||
|
private Entry[string] _cache;
|
||||||
|
|
||||||
|
string[] getImportPathsFor(string compiler) {
|
||||||
|
import dlangui.core.files : findExecutablePath;
|
||||||
|
if (!compiler.length)
|
||||||
|
return [];
|
||||||
|
if (auto p = compiler in _cache) {
|
||||||
|
// found in cache
|
||||||
|
return p.list;
|
||||||
|
}
|
||||||
|
Log.d("Searching for compiler path: ", compiler);
|
||||||
|
import std.path : isAbsolute;
|
||||||
|
string compilerPath = compiler;
|
||||||
|
if (compiler == "default") {
|
||||||
|
// try to autodetect default compiler
|
||||||
|
compilerPath = findExecutablePath("dmd");
|
||||||
|
if (!compilerPath)
|
||||||
|
compilerPath = findExecutablePath("ldc");
|
||||||
|
if (!compilerPath)
|
||||||
|
compilerPath = findExecutablePath("gdc");
|
||||||
|
} else if (compilerPath && !compilerPath.isAbsolute)
|
||||||
|
compilerPath = findExecutablePath(compiler);
|
||||||
|
string[] res;
|
||||||
|
if (compilerPath)
|
||||||
|
res = detectImportPathsForCompiler(compilerPath);
|
||||||
|
else
|
||||||
|
Log.w("Compiler executable not found for `", compiler, "`");
|
||||||
|
Entry newItem = new Entry();
|
||||||
|
newItem.list = res;
|
||||||
|
_cache[compiler] = newItem;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__gshared CompilerImportPathsCache compilerImportPathsCache;
|
||||||
|
|
||||||
|
string[] detectImportPathsForCompiler(string compiler) {
|
||||||
|
string[] res;
|
||||||
|
import std.process : pipeProcess, Redirect, wait;
|
||||||
|
import std.string : startsWith, indexOf;
|
||||||
|
import std.path : buildNormalizedPath;
|
||||||
|
import std.file : write, remove;
|
||||||
|
import dlangui.core.files;
|
||||||
|
try {
|
||||||
|
string sourcefilename = appDataPath(".dlangide") ~ PATH_DELIMITER ~ "tmp_dummy_file_to_get_import_paths.d";
|
||||||
|
write(sourcefilename, "import module_that_does_not_exist;\n");
|
||||||
|
auto pipes = pipeProcess([compiler, sourcefilename], Redirect.stdin | Redirect.stdout | Redirect.stderrToStdout, null, Config.suppressConsole);
|
||||||
|
char[4096] buffer;
|
||||||
|
char[] s = pipes.stdout.rawRead(buffer);
|
||||||
|
wait(pipes.pid);
|
||||||
|
//auto ls = execute([compiler, sourcefilename]);
|
||||||
|
remove(sourcefilename);
|
||||||
|
//string s = ls.output;
|
||||||
|
string[] lines = splitByLines(cast(string)s);
|
||||||
|
debug Log.d("compiler output:\n", s);
|
||||||
|
foreach(line; lines) {
|
||||||
|
if (line.startsWith("import path[")) {
|
||||||
|
auto p = line.indexOf("] = ");
|
||||||
|
if (p > 0) {
|
||||||
|
line = line[p + 4 .. $];
|
||||||
|
string path = line.buildNormalizedPath;
|
||||||
|
debug Log.d("import path found: `", path, "`");
|
||||||
|
res ~= path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue