@@ -15,14 +15,23 @@ import {
15
15
EditorDecoration ,
16
16
TrackedRangeStickiness ,
17
17
} 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' ;
19
21
@injectable ( )
20
- export class EditorDecorations extends Contribution {
22
+ export class CompilerErrors
23
+ extends Contribution
24
+ implements monaco . languages . CodeLensProvider
25
+ {
21
26
@inject ( EditorManager )
22
27
private readonly editorManager : EditorManager ;
23
28
29
+ @inject ( ProtocolToMonacoConverter )
30
+ private readonly p2m : ProtocolToMonacoConverter ;
31
+
24
32
@inject ( CoreErrorHandler )
25
33
private readonly coreErrorHandler : CoreErrorHandler ;
34
+ private readonly compilerErrors = new Map < string , CoreError . Compiler [ ] > ( ) ;
26
35
27
36
private shell : ApplicationShell | undefined ;
28
37
@@ -31,52 +40,89 @@ export class EditorDecorations extends Contribution {
31
40
32
41
override onStart ( app : FrontendApplication ) : void {
33
42
this . shell = app . shell ;
43
+ monaco . languages . registerCodeLensProvider ( InoSelector , this ) ;
34
44
this . coreErrorHandler . onCompilerErrorsDidChange ( ( errors ) =>
35
45
this . handleCompilerErrorsDidChange ( errors )
36
46
) ;
37
47
}
38
48
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
+
39
77
private async handleCompilerErrorsDidChange (
40
78
errors : CoreError . Compiler [ ]
41
79
) : Promise < void > {
42
80
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 )
48
83
) ;
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
+ ] ) ;
49
91
const first = errors [ 0 ] ;
50
92
if ( first ) {
51
93
await this . revealLocationInEditor ( first . location ) ;
52
94
}
53
95
}
54
96
55
97
private async decorateEditors (
56
- errors : CoreError . Compiler [ ]
98
+ errors : Map < string , CoreError . Compiler [ ] >
57
99
) : Promise < Disposable > {
58
100
return new DisposableCollection (
59
101
...( 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
+ )
76
105
) )
77
106
) ;
78
107
}
79
108
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
+
80
126
private async decorateEditor (
81
127
uri : string ,
82
128
errors : CoreError . Compiler [ ]
@@ -112,7 +158,7 @@ export class EditorDecorations extends Contribution {
112
158
}
113
159
114
160
private async registerCodeLens (
115
- errors : CoreError . Compiler [ ]
161
+ errors : Map < string , CoreError . Compiler [ ] >
116
162
) : Promise < Disposable > {
117
163
return new DisposableCollection ( ) ;
118
164
}
0 commit comments