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;
|
||||
override void getDocComments(DSourceEdit editor, TextPosition caretPosition, void delegate(string[]) callback) {
|
||||
cancelGetDocComments();
|
||||
string[] importPaths = editor.importPaths();
|
||||
string[] importPaths = editor.importPaths(_frame.settings);
|
||||
string content = toUTF8(editor.text);
|
||||
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
||||
if (!isAtWord(content, byteOffset))
|
||||
|
@ -88,7 +88,7 @@ class DEditorTool : EditorTool
|
|||
DCDTask _goToDefinitionTask;
|
||||
override void goToDefinition(DSourceEdit editor, TextPosition caretPosition) {
|
||||
cancelGoToDefinition();
|
||||
string[] importPaths = editor.importPaths();
|
||||
string[] importPaths = editor.importPaths(_frame.settings);
|
||||
string content = toUTF8(editor.text);
|
||||
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
||||
|
||||
|
@ -129,7 +129,7 @@ class DEditorTool : EditorTool
|
|||
DCDTask _getCompletionsTask;
|
||||
override void getCompletions(DSourceEdit editor, TextPosition caretPosition, void delegate(dstring[] completions, string[] icons, CompletionTypes type) callback) {
|
||||
cancelGetCompletions();
|
||||
string[] importPaths = editor.importPaths();
|
||||
string[] importPaths = editor.importPaths(_frame.settings);
|
||||
|
||||
string content = toUTF8(editor.text);
|
||||
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
|
||||
string[] importPaths() {
|
||||
string[] importPaths(IDESettings ideSettings) {
|
||||
if (_projectSourceFile)
|
||||
return _projectSourceFile.project.importPaths;
|
||||
return _projectSourceFile.project.importPaths(ideSettings);
|
||||
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, 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));
|
||||
dumpCompilerPath("DMD", dmdPath);
|
||||
dumpCompilerPath("dmd", dmdPath);
|
||||
_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));
|
||||
dumpCompilerPath("GDC", gdcPath);
|
||||
dumpCompilerPath("gdc", gdcPath);
|
||||
}
|
||||
private void dumpCompilerPath(dstring compilerName, string compiler) {
|
||||
private void dumpCompilerPath(string compilerName, string compiler) {
|
||||
if (!compiler)
|
||||
return;
|
||||
if (compiler) {
|
||||
string[] imports = detectImportPathsForCompiler(compiler);
|
||||
string[] imports = compilerImportPathsCache.getImportPathsFor(compilerName);
|
||||
if (imports.length > 0) {
|
||||
Log.d(compilerName, " imports:", imports);
|
||||
_logPanel.appendText(null, compilerName ~ " imports:\n"d);
|
||||
_logPanel.appendText(null, to!dstring(compilerName) ~ " imports:\n"d);
|
||||
foreach(s; imports)
|
||||
_logPanel.appendText(null, " "d ~ to!dstring(s) ~ "\n"d);
|
||||
}
|
||||
|
@ -1601,7 +1601,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL
|
|||
}
|
||||
|
||||
public void warmUpImportPaths(Project project) {
|
||||
dcdInterface.warmUp(project.importPaths);
|
||||
dcdInterface.warmUp(project.importPaths(_settings));
|
||||
}
|
||||
|
||||
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
|
||||
struct ProjectConfiguration {
|
||||
/// name used to build the project
|
||||
|
@ -384,6 +361,7 @@ struct ProjectConfiguration {
|
|||
|
||||
/// DLANGIDE D project
|
||||
class Project : WorkspaceItem {
|
||||
import dlangide.workspace.idesettings : IDESettings;
|
||||
protected Workspace _workspace;
|
||||
protected bool _opened;
|
||||
protected ProjectFolder _items;
|
||||
|
@ -397,7 +375,6 @@ class Project : WorkspaceItem {
|
|||
protected string _dependencyVersion;
|
||||
|
||||
protected string[] _sourcePaths;
|
||||
protected string[] _builderSourcePaths;
|
||||
protected ProjectConfiguration[] _configurations;
|
||||
protected ProjectConfiguration _projectConfiguration = ProjectConfiguration.DEFAULT;
|
||||
|
||||
|
@ -529,12 +506,12 @@ class Project : WorkspaceItem {
|
|||
|
||||
/// returns project's own source paths
|
||||
@property string[] sourcePaths() { return _sourcePaths; }
|
||||
/// returns project's own source paths
|
||||
@property string[] builderSourcePaths() {
|
||||
if (!_builderSourcePaths) {
|
||||
_builderSourcePaths = dmdSourcePaths();
|
||||
}
|
||||
return _builderSourcePaths;
|
||||
/// returns project's current toolchain import paths
|
||||
string[] builderSourcePaths(IDESettings ideSettings) {
|
||||
string compilerName = settings.getToolchain(ideSettings);
|
||||
if (!compilerName)
|
||||
compilerName = "default";
|
||||
return compilerImportPathsCache.getImportPathsFor(compilerName);
|
||||
}
|
||||
|
||||
/// returns first source folder for project or null if not found
|
||||
|
@ -556,10 +533,10 @@ class Project : WorkspaceItem {
|
|||
dst ~= item;
|
||||
}
|
||||
}
|
||||
@property string[] importPaths() {
|
||||
@property string[] importPaths(IDESettings ideSettings) {
|
||||
string[] res;
|
||||
addUnique(res, sourcePaths);
|
||||
addUnique(res, builderSourcePaths);
|
||||
addUnique(res, builderSourcePaths(ideSettings));
|
||||
foreach(dep; _dependencies) {
|
||||
addUnique(res, dep.sourcePaths);
|
||||
}
|
||||
|
@ -805,7 +782,7 @@ class Project : WorkspaceItem {
|
|||
findMainSourceFile();
|
||||
|
||||
Log.i("Project source paths: ", sourcePaths);
|
||||
Log.i("Builder source paths: ", builderSourcePaths);
|
||||
//Log.i("Builder source paths: ", builderSourcePaths(_settings));
|
||||
if (!_isDependency)
|
||||
loadSelections();
|
||||
|
||||
|
@ -1003,3 +980,99 @@ class EditorBookmark {
|
|||
int line;
|
||||
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