diff --git a/src/dlangide/ui/dsourceedit.d b/src/dlangide/ui/dsourceedit.d index 083101c..950be2d 100644 --- a/src/dlangide/ui/dsourceedit.d +++ b/src/dlangide/ui/dsourceedit.d @@ -83,6 +83,14 @@ class DSourceEdit : SourceEdit { } return super.handleAction(a); } + + /// change caret position and ensure it is visible + void setCaretPos(int line, int column) + { + _caretPos = TextPosition(line,column); + invalidate(); + ensureCaretVisible(); + } } diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index 4638847..5bf3025 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -87,6 +87,19 @@ class IDEFrame : AppFrame { return openSourceFile(file.filename, file, activate); } + /// + bool onCompilerLogIssueClick(dstring filename, int line, int column) + { + Log.d("onCompilerLogIssueClick ", filename); + + import std.conv:to; + openSourceFile(to!string(filename)); + + currentEditor().setCaretPos(line-1,column); + + return true; + } + void onModifiedStateChange(Widget source, bool modified) { // Log.d("onModifiedStateChange ", source.id, " modified=", modified); @@ -99,9 +112,15 @@ class IDEFrame : AppFrame { bool openSourceFile(string filename, ProjectSourceFile file = null, bool activate = true) { if (!file) - file = _wsPanel.findSourceFileItem(filename); - Log.d("openSourceFile ", filename); - int index = _tabs.tabIndex(filename); + file = _wsPanel.findSourceFileItem(filename, false); + + if(!file) + return false; + + filename = file.filename; + + Log.d("openSourceFile ", filename); + int index = _tabs.tabIndex(filename); if (index >= 0) { // file is already opened in tab _tabs.selectTab(index, true); @@ -279,6 +298,7 @@ class IDEFrame : AppFrame { _dockHost.addDockedWindow(_wsPanel); _logPanel = new OutputPanel("output"); + _logPanel.compilerLogIssueClickHandler = &onCompilerLogIssueClick; _logPanel.appendText(null, "DlangIDE is started\nHINT: Try to open some DUB project\n"d); _dockHost.addDockedWindow(_logPanel); diff --git a/src/dlangide/ui/outputpanel.d b/src/dlangide/ui/outputpanel.d index c6937a4..5b1f695 100644 --- a/src/dlangide/ui/outputpanel.d +++ b/src/dlangide/ui/outputpanel.d @@ -5,9 +5,58 @@ import dlangide.workspace.workspace; import dlangide.workspace.project; import std.utf; +import std.regex; +/// +interface CompilerLogIssueClickHandler { + bool onCompilerLogIssueClick(dstring filename, int line, int column); +} + +/// +class CompilerLogWidget : LogWidget { + + Signal!CompilerLogIssueClickHandler compilerLogIssueClickHandler; + + auto ctr = ctRegex!(r"(.+)\((\d+)\): (Error|Warning): (.+)"d); + + /// forward to super c'tor + this(string ID) { + super(ID); + } + + /// + override bool onMouseEvent(MouseEvent event) { + + if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) { + super.onMouseEvent(event); + + auto logLine = this.content.line(this._caretPos.line); + + //src\tetris.d(49): Error: found 'return' when expecting ';' following statement + + auto match = matchFirst(logLine, ctr); + + if(!match.empty) + { + if (compilerLogIssueClickHandler.assigned) { + import std.conv:to; + compilerLogIssueClickHandler(match[1], to!int(match[2]), 0); + } + } + + return true; + } + + return super.onMouseEvent(event); + } +} + +/// class OutputPanel : DockWindow { - protected LogWidget _logWidget; + + Signal!CompilerLogIssueClickHandler compilerLogIssueClickHandler; + + protected CompilerLogWidget _logWidget; this(string id) { super(id); @@ -16,9 +65,10 @@ class OutputPanel : DockWindow { } override protected Widget createBodyWidget() { - _logWidget = new LogWidget("logwidget"); + _logWidget = new CompilerLogWidget("logwidget"); _logWidget.readOnly = true; _logWidget.layoutHeight(FILL_PARENT).layoutHeight(FILL_PARENT); + _logWidget.compilerLogIssueClickHandler = &onIssueClick; return _logWidget; } @@ -45,4 +95,13 @@ class OutputPanel : DockWindow { void clear(string category = null) { _logWidget.text = ""d; } + + private bool onIssueClick(dstring fn, int line, int column) + { + if (compilerLogIssueClickHandler.assigned) { + compilerLogIssueClickHandler(fn, line, column); + } + + return true; + } } diff --git a/src/dlangide/ui/wspanel.d b/src/dlangide/ui/wspanel.d index 803efaf..e93f226 100644 --- a/src/dlangide/ui/wspanel.d +++ b/src/dlangide/ui/wspanel.d @@ -72,9 +72,9 @@ class WorkspacePanel : DockWindow { return _workspace; } - ProjectSourceFile findSourceFileItem(string filename) { + ProjectSourceFile findSourceFileItem(string filename, bool fullFileName=true) { if (_workspace) - return _workspace.findSourceFileItem(filename); + return _workspace.findSourceFileItem(filename, fullFileName); return null; } diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index b5c22bc..94a8a66 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -260,24 +260,29 @@ class Project : WorkspaceItem { } /// tries to find source file in project, returns found project source file item, or null if not found - ProjectSourceFile findSourceFileItem(ProjectItem dir, string filename) { + ProjectSourceFile findSourceFileItem(ProjectItem dir, string filename, bool fullFileName=true) { for (int i = 0; i < dir.childCount; i++) { ProjectItem item = dir.child(i); if (item.isFolder) { - ProjectSourceFile res = findSourceFileItem(item, filename); + ProjectSourceFile res = findSourceFileItem(item, filename, fullFileName); if (res) return res; } else { ProjectSourceFile res = cast(ProjectSourceFile)item; - if (res && res.filename.equal(filename)) - return res; + if(res) + { + if(fullFileName && res.filename.equal(filename)) + return res; + else if (!fullFileName && res.filename.endsWith(filename)) + return res; + } } } return null; } - ProjectSourceFile findSourceFileItem(string filename) { - return findSourceFileItem(_items, filename); + ProjectSourceFile findSourceFileItem(string filename, bool fullFileName=true) { + return findSourceFileItem(_items, filename, fullFileName); } override bool load(string fname = null) { diff --git a/src/dlangide/workspace/workspace.d b/src/dlangide/workspace/workspace.d index dbd5cba..02244f2 100644 --- a/src/dlangide/workspace/workspace.d +++ b/src/dlangide/workspace/workspace.d @@ -69,9 +69,9 @@ class Workspace : WorkspaceItem { } /// tries to find source file in one of projects, returns found project source file item, or null if not found - ProjectSourceFile findSourceFileItem(string filename) { + ProjectSourceFile findSourceFileItem(string filename, bool fullFileName=true) { foreach (Project p; _projects) { - ProjectSourceFile res = p.findSourceFileItem(filename); + ProjectSourceFile res = p.findSourceFileItem(filename, fullFileName); if (res) return res; }