mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 07:04:04 -05:00
Make quickfix suggestions clickable in the compiler output pane
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import * as monaco from 'monaco-editor';
|
||||
import {ClangirBackendOptions} from '../types/compilation/clangir.interfaces.js';
|
||||
import {CompilationResult} from '../types/compilation/compilation.interfaces.js';
|
||||
import {LLVMIrBackendOptions} from '../types/compilation/ir.interfaces.js';
|
||||
@@ -80,6 +81,7 @@ export type EventMap = {
|
||||
editorClose: (editorId: number) => void;
|
||||
editorDisplayFlow: (editorId: number, flow: MessageWithLocation[]) => void;
|
||||
editorLinkLine: (editorId: number, lineNumber: number, colBegin: number, colEnd: number, reveal: boolean) => void;
|
||||
editorApplyQuickfix: (editorId: number, range: monaco.IRange, text: string | null) => void;
|
||||
editorOpen: (editorId: number) => void;
|
||||
editorSetDecoration: (editorId: number, lineNumber: number, reveal: boolean, column?: number) => void;
|
||||
executeResult: (executorId: number, compiler: any, result: any, language: Language) => void;
|
||||
|
||||
@@ -357,6 +357,7 @@ export class Editor extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Edit
|
||||
this.eventHub.on('editorSetDecoration', this.onEditorSetDecoration, this);
|
||||
this.eventHub.on('editorDisplayFlow', this.onEditorDisplayFlow, this);
|
||||
this.eventHub.on('editorLinkLine', this.onEditorLinkLine, this);
|
||||
this.eventHub.on('editorApplyQuickfix', this.onEditorApplyQuickfix, this);
|
||||
this.eventHub.on('conformanceViewOpen', this.onConformanceViewOpen, this);
|
||||
this.eventHub.on('conformanceViewClose', this.onConformanceViewClose, this);
|
||||
this.eventHub.on('newSource', this.onNewSource, this);
|
||||
@@ -1114,13 +1115,7 @@ export class Editor extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Edit
|
||||
);
|
||||
}
|
||||
|
||||
updateSource(newSource: string): void {
|
||||
// Create something that looks like an edit operation for the whole text
|
||||
const operation = {
|
||||
range: this.editor.getModel()?.getFullModelRange(),
|
||||
forceMoveMarkers: true,
|
||||
text: newSource,
|
||||
};
|
||||
applyEdit(operation: monaco.editor.IIdentifiedSingleEditOperation): void {
|
||||
const nullFn = () => {
|
||||
return null;
|
||||
};
|
||||
@@ -1132,6 +1127,16 @@ export class Editor extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Edit
|
||||
// @ts-expect-error: See above comment maybe
|
||||
this.editor.getModel()?.pushEditOperations(viewState?.cursorState ?? null, [operation], nullFn);
|
||||
this.numberUsedLines();
|
||||
}
|
||||
|
||||
updateSource(newSource: string): void {
|
||||
// Create something that looks like an edit operation for the whole text
|
||||
const operation = {
|
||||
range: this.editor.getModel()!.getFullModelRange(),
|
||||
forceMoveMarkers: true,
|
||||
text: newSource,
|
||||
};
|
||||
this.applyEdit(operation);
|
||||
|
||||
if (!this.awaitingInitialResults) {
|
||||
if (this.selection) {
|
||||
@@ -1755,6 +1760,12 @@ export class Editor extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Edit
|
||||
}
|
||||
}
|
||||
|
||||
onEditorApplyQuickfix(editorId: number, range: monaco.IRange, text: string | null): void {
|
||||
if (editorId === this.id) {
|
||||
this.applyEdit({forceMoveMarkers: true, range, text});
|
||||
}
|
||||
}
|
||||
|
||||
onEditorSetDecoration(id: number, lineNum: number, reveal: boolean, column?: number): void {
|
||||
if (Number(id) === this.id) {
|
||||
if (reveal && lineNum) {
|
||||
|
||||
@@ -24,10 +24,12 @@
|
||||
|
||||
import {Container} from 'golden-layout';
|
||||
import $ from 'jquery';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import _ from 'underscore';
|
||||
import {escapeHTML} from '../../shared/common-utils.js';
|
||||
import {CompilationResult} from '../../types/compilation/compilation.interfaces.js';
|
||||
import {CompilerInfo} from '../../types/compiler.interfaces.js';
|
||||
import {Fix} from '../../types/resultline/resultline.interfaces.js';
|
||||
import * as AnsiToHtml from '../ansi-to-html.js';
|
||||
import {Hub} from '../hub.js';
|
||||
import {updateAndCalcTopBarHeight} from '../utils.js';
|
||||
@@ -172,7 +174,13 @@ export class Output extends Pane<OutputState> {
|
||||
if (obj.text === '') {
|
||||
this.add('<br/>');
|
||||
} else {
|
||||
this.add(this.normalAnsiToHtml.toHtml(obj.text), lineNumber, columnNumber, obj.tag?.file);
|
||||
this.add(
|
||||
this.normalAnsiToHtml.toHtml(obj.text),
|
||||
lineNumber,
|
||||
columnNumber,
|
||||
obj.tag?.file,
|
||||
obj.tag?.fixes,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,11 +283,22 @@ export class Output extends Pane<OutputState> {
|
||||
}
|
||||
}
|
||||
|
||||
add(msg: string, lineNum?: number, column?: number, filename?: string) {
|
||||
emitEditorApplyQuickfix(filename: string, range: monaco.IRange, text: string | null): void {
|
||||
if (this.compilerInfo.editorId) {
|
||||
this.eventHub.emit('editorApplyQuickfix', this.compilerInfo.editorId, range, text);
|
||||
} else if (filename) {
|
||||
const editorId = this.getEditorIdByFilename(filename);
|
||||
if (editorId) {
|
||||
this.eventHub.emit('editorApplyQuickfix', editorId, range, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add(msg: string, lineNum?: number, column?: number, filename?: string, fixes?: Fix[]) {
|
||||
const elem = $('<div/>').appendTo(this.contentRoot);
|
||||
if (lineNum && column && filename) {
|
||||
elem.empty();
|
||||
$('<span class="linked-compiler-output-line"></span>')
|
||||
const span = $('<span class="linked-compiler-output-line"></span>')
|
||||
.html(msg)
|
||||
.on('click', e => {
|
||||
this.emitEditorLinkLine(lineNum, column, filename, true);
|
||||
@@ -288,18 +307,51 @@ export class Output extends Pane<OutputState> {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
})
|
||||
.on('click', '.diagnostic-url', e => {
|
||||
e.stopPropagation();
|
||||
})
|
||||
.on('mouseover', () => {
|
||||
this.emitEditorLinkLine(lineNum, column, filename, false);
|
||||
})
|
||||
.appendTo(elem);
|
||||
.on('click', '.diagnostic-url', e => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
if (fixes) {
|
||||
this.addQuickfixHandlers(span, msg, fixes, filename);
|
||||
}
|
||||
|
||||
span.appendTo(elem);
|
||||
} else {
|
||||
elem.html(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private addQuickfixHandlers(span: JQuery<HTMLElement>, msg: string, fixes: Fix[], filename: string): void {
|
||||
if (fixes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
span.attr('title', fixes[0].title).addClass('quickfix-action');
|
||||
for (const fix of fixes) {
|
||||
span.on('click', e => {
|
||||
for (const {text, line, endline, column, endcolumn} of fix.edits) {
|
||||
if (line && endline && column && endcolumn) {
|
||||
this.emitEditorApplyQuickfix(
|
||||
filename,
|
||||
{
|
||||
startLineNumber: line,
|
||||
startColumn: column,
|
||||
endLineNumber: endline,
|
||||
endColumn: endcolumn,
|
||||
},
|
||||
text,
|
||||
);
|
||||
}
|
||||
}
|
||||
$(e.delegateTarget).replaceWith($('<span></span>').html(msg));
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
override getDefaultPaneName() {
|
||||
return `Output of ${this.compilerInfo.compilerName}`;
|
||||
}
|
||||
|
||||
@@ -705,6 +705,24 @@ kbd {
|
||||
color: var(--terminal-bright-blue) !important;
|
||||
}
|
||||
|
||||
.quickfix-action:hover {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.quickfix-action::after {
|
||||
font-style: normal;
|
||||
content: '💡';
|
||||
border: 1px solid var(--terminal-bright-blue);
|
||||
margin-left: 3em;
|
||||
border-radius: 5px;
|
||||
padding: 3px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.quickfix-action:hover:after {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.lm_content {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
@@ -745,4 +745,12 @@ textarea.form-control {
|
||||
color: #ffda6a !important;
|
||||
}
|
||||
|
||||
.quickfix-action::after {
|
||||
background: color.adjust(#333, $lightness: 15%);
|
||||
}
|
||||
|
||||
.quickfix-action:hover:after {
|
||||
background: color.adjust(#333, $lightness: 25%);
|
||||
}
|
||||
|
||||
} // End html[data-theme='dark']
|
||||
|
||||
Reference in New Issue
Block a user