Skip to content

Commit 3385566

Browse files
author
Akos Kitta
committed
code lens skeleton.
Signed-off-by: Akos Kitta <[email protected]>
1 parent c71c830 commit 3385566

File tree

4 files changed

+89
-39
lines changed

4 files changed

+89
-39
lines changed

arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ import { PreferenceTreeGenerator as TheiaPreferenceTreeGenerator } from '@theia/
292292
import { AboutDialog } from './theia/core/about-dialog';
293293
import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog';
294294
import { CoreErrorHandler } from './contributions/core-error-handler';
295-
import { EditorDecorations } from './contributions/editor-decorations';
295+
import { CompilerErrors } from './contributions/editor-decorations';
296296

297297
MonacoThemingService.register({
298298
id: 'arduino-theme',
@@ -671,7 +671,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
671671
Contribution.configure(bind, AddZipLibrary);
672672
Contribution.configure(bind, PlotterFrontendContribution);
673673
Contribution.configure(bind, Format);
674-
Contribution.configure(bind, EditorDecorations);
674+
Contribution.configure(bind, CompilerErrors);
675675

676676
// Disabled the quick-pick customization from Theia when multiple formatters are available.
677677
// Use the default VS Code behavior, and pick the first one. In the IDE2, clang-format has `exclusive` selectors.

arduino-ide-extension/src/browser/contributions/editor-decorations.ts

+71-25
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,23 @@ import {
1515
EditorDecoration,
1616
TrackedRangeStickiness,
1717
} from '@theia/editor/lib/browser/decorations/editor-decoration';
18-
18+
import * as monaco from '@theia/monaco-editor-core';
19+
import { InoSelector } from '../ino-selectors';
20+
import { ProtocolToMonacoConverter } from '@theia/monaco/lib/browser/protocol-to-monaco-converter';
1921
@injectable()
20-
export class EditorDecorations extends Contribution {
22+
export class CompilerErrors
23+
extends Contribution
24+
implements monaco.languages.CodeLensProvider
25+
{
2126
@inject(EditorManager)
2227
private readonly editorManager: EditorManager;
2328

29+
@inject(ProtocolToMonacoConverter)
30+
private readonly p2m: ProtocolToMonacoConverter;
31+
2432
@inject(CoreErrorHandler)
2533
private readonly coreErrorHandler: CoreErrorHandler;
34+
private readonly compilerErrors = new Map<string, CoreError.Compiler[]>();
2635

2736
private shell: ApplicationShell | undefined;
2837

@@ -31,52 +40,89 @@ export class EditorDecorations extends Contribution {
3140

3241
override onStart(app: FrontendApplication): void {
3342
this.shell = app.shell;
43+
monaco.languages.registerCodeLensProvider(InoSelector, this);
3444
this.coreErrorHandler.onCompilerErrorsDidChange((errors) =>
3545
this.handleCompilerErrorsDidChange(errors)
3646
);
3747
}
3848

49+
provideCodeLenses(
50+
model: monaco.editor.ITextModel,
51+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
52+
_token: monaco.CancellationToken
53+
): monaco.languages.ProviderResult<monaco.languages.CodeLensList> {
54+
const lenses: monaco.languages.CodeLens[] = [];
55+
const errors = this.compilerErrors.get(model.uri.toString());
56+
// Do not show "jump next" when one is available
57+
if (errors && errors.length > 1) {
58+
errors.forEach((error, index, self) => {
59+
lenses.push({
60+
range: this.p2m.asRange(error.location.range),
61+
command: {
62+
id: 'some-id',
63+
title: 'hey',
64+
tooltip: 'blabla',
65+
},
66+
});
67+
});
68+
}
69+
return {
70+
lenses,
71+
dispose: () => {
72+
/*noop*/
73+
},
74+
};
75+
}
76+
3977
private async handleCompilerErrorsDidChange(
4078
errors: CoreError.Compiler[]
4179
): Promise<void> {
4280
this.toDisposeOnCompilerErrorDidChange.dispose();
43-
this.toDisposeOnCompilerErrorDidChange.pushAll(
44-
await Promise.all([
45-
this.decorateEditors(errors),
46-
this.registerCodeLens(errors),
47-
])
81+
Array.from(this.groupByResource(errors).entries()).forEach(([uri, error]) =>
82+
this.compilerErrors.set(uri, error)
4883
);
84+
this.toDisposeOnCompilerErrorDidChange.pushAll([
85+
Disposable.create(() => this.compilerErrors.clear()),
86+
...(await Promise.all([
87+
this.decorateEditors(this.compilerErrors),
88+
this.registerCodeLens(this.compilerErrors),
89+
])),
90+
]);
4991
const first = errors[0];
5092
if (first) {
5193
await this.revealLocationInEditor(first.location);
5294
}
5395
}
5496

5597
private async decorateEditors(
56-
errors: CoreError.Compiler[]
98+
errors: Map<string, CoreError.Compiler[]>
5799
): Promise<Disposable> {
58100
return new DisposableCollection(
59101
...(await Promise.all(
60-
[
61-
...errors
62-
.reduce((acc, curr) => {
63-
const {
64-
location: { uri },
65-
} = curr;
66-
let errors = acc.get(uri);
67-
if (!errors) {
68-
errors = [];
69-
acc.set(uri, errors);
70-
}
71-
errors.push(curr);
72-
return acc;
73-
}, new Map<string, CoreError.Compiler[]>())
74-
.entries(),
75-
].map(([uri, errors]) => this.decorateEditor(uri, errors))
102+
[...errors.entries()].map(([uri, errors]) =>
103+
this.decorateEditor(uri, errors)
104+
)
76105
))
77106
);
78107
}
79108

109+
private groupByResource(
110+
errors: CoreError.Compiler[]
111+
): Map<string, CoreError.Compiler[]> {
112+
return errors.reduce((acc, curr) => {
113+
const {
114+
location: { uri },
115+
} = curr;
116+
let errors = acc.get(uri);
117+
if (!errors) {
118+
errors = [];
119+
acc.set(uri, errors);
120+
}
121+
errors.push(curr);
122+
return acc;
123+
}, new Map<string, CoreError.Compiler[]>());
124+
}
125+
80126
private async decorateEditor(
81127
uri: string,
82128
errors: CoreError.Compiler[]
@@ -112,7 +158,7 @@ export class EditorDecorations extends Contribution {
112158
}
113159

114160
private async registerCodeLens(
115-
errors: CoreError.Compiler[]
161+
errors: Map<string, CoreError.Compiler[]>
116162
): Promise<Disposable> {
117163
return new DisposableCollection();
118164
}

arduino-ide-extension/src/browser/contributions/format.ts

+3-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { MaybePromise } from '@theia/core';
22
import { inject, injectable } from '@theia/core/shared/inversify';
33
import * as monaco from '@theia/monaco-editor-core';
44
import { Formatter } from '../../common/protocol/formatter';
5+
import { InoSelector } from '../ino-selectors';
56
import { Contribution, URI } from './contribution';
67

78
@injectable()
@@ -15,12 +16,11 @@ export class Format
1516
private readonly formatter: Formatter;
1617

1718
override onStart(): MaybePromise<void> {
18-
const selector = this.selectorOf('ino', 'c', 'cpp', 'h', 'hpp', 'pde');
1919
monaco.languages.registerDocumentRangeFormattingEditProvider(
20-
selector,
20+
InoSelector,
2121
this
2222
);
23-
monaco.languages.registerDocumentFormattingEditProvider(selector, this);
23+
monaco.languages.registerDocumentFormattingEditProvider(InoSelector, this);
2424
}
2525
async provideDocumentRangeFormattingEdits(
2626
model: monaco.editor.ITextModel,
@@ -82,13 +82,4 @@ export class Format
8282
options,
8383
});
8484
}
85-
86-
private selectorOf(
87-
...languageId: string[]
88-
): monaco.languages.LanguageSelector {
89-
return languageId.map((language) => ({
90-
language,
91-
exclusive: true, // <-- this should make sure the custom formatter has higher precedence over the LS formatter.
92-
}));
93-
}
9485
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as monaco from '@theia/monaco-editor-core';
2+
/**
3+
* Exclusive "ino" document selector for monaco.
4+
*/
5+
export const InoSelector = selectorOf('ino', 'c', 'cpp', 'h', 'hpp', 'pde');
6+
function selectorOf(
7+
...languageId: string[]
8+
): monaco.languages.LanguageSelector {
9+
return languageId.map((language) => ({
10+
language,
11+
exclusive: true, // <-- this should make sure the custom formatter has higher precedence over the LS formatter.
12+
}));
13+
}

0 commit comments

Comments
 (0)