@@ -29,7 +29,7 @@ import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/edito
2929import { ICodeEditor } from 'vs/editor/browser/editorBrowser' ;
3030import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions' ;
3131import { IOptions , ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget' ;
32- import { getCodeActions } from 'vs/editor/contrib/quickFix/common/quickFix' ;
32+ import { getCodeActions , IQuickFix2 } from 'vs/editor/contrib/quickFix/common/quickFix' ;
3333
3434class MarkerModel {
3535
@@ -181,6 +181,117 @@ class MarkerModel {
181181 }
182182}
183183
184+ class FixesWidget {
185+
186+ domNode : HTMLDivElement ;
187+
188+ private _disposeOnUpdate : IDisposable [ ] = [ ] ;
189+ private _listener : IDisposable ;
190+
191+ constructor (
192+ container : HTMLElement ,
193+ @IKeybindingService private _keybindingService : IKeybindingService
194+ ) {
195+ this . domNode = document . createElement ( 'div' ) ;
196+ container . appendChild ( this . domNode ) ;
197+
198+ this . _listener = dom . addStandardDisposableListener ( container , 'keydown' , ( e ) => {
199+ switch ( e . asKeybinding ( ) ) {
200+ case CommonKeybindings . LEFT_ARROW :
201+ this . _move ( true ) ;
202+ // this._goLeft();
203+ e . preventDefault ( ) ;
204+ e . stopPropagation ( ) ;
205+ break ;
206+ case CommonKeybindings . RIGHT_ARROW :
207+ this . _move ( false ) ;
208+ // this._goRight();
209+ e . preventDefault ( ) ;
210+ e . stopPropagation ( ) ;
211+ break ;
212+ }
213+ } ) ;
214+ }
215+
216+ dispose ( ) : void {
217+ this . _disposeOnUpdate = dispose ( this . _disposeOnUpdate ) ;
218+ this . _listener = dispose ( this . _listener ) ;
219+ }
220+
221+ update ( fixes : TPromise < IQuickFix2 [ ] > ) : TPromise < any > {
222+ this . _disposeOnUpdate = dispose ( this . _disposeOnUpdate ) ;
223+ this . domNode . style . display = 'none' ;
224+ return fixes . then ( fixes => this . _doUpdate ( fixes ) , onUnexpectedError ) ;
225+ }
226+
227+ private _doUpdate ( fixes : IQuickFix2 [ ] ) : void {
228+
229+ dom . clearNode ( this . domNode ) ;
230+
231+ if ( ! fixes || fixes . length === 0 ) {
232+ return ;
233+ }
234+
235+ // light bulb and label
236+ let quickfixhead = document . createElement ( 'span' ) ;
237+ quickfixhead . className = 'quickfixhead' ;
238+ quickfixhead . appendChild ( document . createTextNode ( fixes . length > 1
239+ ? nls . localize ( 'quickfix.multiple.label' , 'Suggested fixes: ' )
240+ : nls . localize ( 'quickfix.single.label' , 'Suggested fix: ' ) ) ) ;
241+ this . domNode . appendChild ( quickfixhead ) ;
242+
243+ // each fix as entry
244+ const container = document . createElement ( 'span' ) ;
245+ container . className = 'quickfixcontainer' ;
246+
247+ fixes . forEach ( ( fix , idx , arr ) => {
248+
249+ if ( idx > 0 ) {
250+ let separator = document . createElement ( 'span' ) ;
251+ separator . appendChild ( document . createTextNode ( ', ' ) ) ;
252+ container . appendChild ( separator ) ;
253+ }
254+
255+ let entry = document . createElement ( 'a' ) ;
256+ entry . tabIndex = 0 ;
257+ entry . className = `quickfixentry` ;
258+ entry . dataset [ 'idx' ] = String ( idx ) ;
259+ entry . dataset [ 'next' ] = String ( idx < arr . length - 1 ? idx + 1 : 0 ) ;
260+ entry . dataset [ 'prev' ] = String ( idx > 0 ? idx - 1 : arr . length - 1 ) ;
261+ entry . appendChild ( document . createTextNode ( fix . command . title ) ) ;
262+ this . _disposeOnUpdate . push ( dom . addDisposableListener ( entry , dom . EventType . CLICK , ( ) => {
263+ this . _keybindingService . executeCommand ( fix . command . id , ...fix . command . arguments ) ;
264+ return true ;
265+ } ) ) ;
266+ this . _disposeOnUpdate . push ( dom . addStandardDisposableListener ( entry , 'keydown' , ( e ) => {
267+ switch ( e . asKeybinding ( ) ) {
268+ case CommonKeybindings . ENTER :
269+ case CommonKeybindings . SPACE :
270+ this . _keybindingService . executeCommand ( fix . command . id , ...fix . command . arguments ) ;
271+ e . preventDefault ( ) ;
272+ e . stopPropagation ( ) ;
273+ }
274+ } ) ) ;
275+ container . appendChild ( entry ) ;
276+ } ) ;
277+
278+ this . domNode . appendChild ( container ) ;
279+ this . domNode . style . display = '' ;
280+ }
281+
282+ private _move ( left : boolean ) : void {
283+ let target : HTMLElement ;
284+ if ( document . activeElement . classList . contains ( 'quickfixentry' ) ) {
285+ let current = < HTMLElement > document . activeElement ;
286+ let idx = left ? current . dataset [ 'prev' ] : current . dataset [ 'next' ] ;
287+ target = < HTMLElement > this . domNode . querySelector ( `a[data-idx='${ idx } ']` ) ;
288+ } else {
289+ target = < HTMLElement > this . domNode . querySelector ( '.quickfixentry' ) ;
290+ }
291+ target . focus ( ) ;
292+ }
293+ }
294+
184295var zoneOptions : IOptions = {
185296 showFrame : true ,
186297 showArrow : true ,
@@ -191,10 +302,8 @@ class MarkerNavigationWidget extends ZoneWidget {
191302
192303 private _container : HTMLElement ;
193304 private _element : HTMLElement ;
194- private _quickFixSection : HTMLElement ;
305+ private _fixesWidget : FixesWidget ;
195306 private _callOnDispose : IDisposable [ ] = [ ] ;
196- private _localCleanup : IDisposable [ ] = [ ] ;
197- private _quickFixEntries : HTMLElement [ ] ;
198307
199308 constructor ( editor : ICodeEditor , private _model : MarkerModel , private _keybindingService : IKeybindingService ) {
200309 super ( editor , zoneOptions ) ;
@@ -215,45 +324,8 @@ class MarkerNavigationWidget extends ZoneWidget {
215324 this . _element . setAttribute ( 'role' , 'alert' ) ;
216325 this . _container . appendChild ( this . _element ) ;
217326
218- this . _quickFixSection = document . createElement ( 'div' ) ;
219- this . _container . appendChild ( this . _quickFixSection ) ;
220-
221- this . _callOnDispose . push ( dom . addStandardDisposableListener ( this . _container , 'keydown' , ( e ) => {
222- switch ( e . asKeybinding ( ) ) {
223- case CommonKeybindings . LEFT_ARROW :
224- this . _goLeft ( ) ;
225- e . preventDefault ( ) ;
226- e . stopPropagation ( ) ;
227- break ;
228- case CommonKeybindings . RIGHT_ARROW :
229- this . _goRight ( ) ;
230- e . preventDefault ( ) ;
231- e . stopPropagation ( ) ;
232- break ;
233-
234- }
235- } ) ) ;
236- }
237-
238- private _goLeft ( ) : void {
239- if ( ! this . _quickFixEntries ) {
240- return ;
241- }
242- let idx = this . _quickFixEntries . indexOf ( < HTMLElement > document . activeElement ) ;
243- if ( idx === - 1 ) {
244- idx = 1 ;
245- }
246- idx = ( idx + this . _quickFixEntries . length - 1 ) % this . _quickFixEntries . length ;
247- this . _quickFixEntries [ idx ] . focus ( ) ;
248- }
249-
250- private _goRight ( ) : void {
251- if ( ! this . _quickFixEntries ) {
252- return ;
253- }
254- let idx = this . _quickFixEntries . indexOf ( < HTMLElement > document . activeElement ) ;
255- idx = ( idx + 1 ) % this . _quickFixEntries . length ;
256- this . _quickFixEntries [ idx ] . focus ( ) ;
327+ this . _fixesWidget = new FixesWidget ( this . _container , this . _keybindingService ) ;
328+ this . _callOnDispose . push ( this . _fixesWidget ) ;
257329 }
258330
259331 public show ( where : editorCommon . IPosition , heightInLines : number ) : void {
@@ -282,8 +354,6 @@ class MarkerNavigationWidget extends ZoneWidget {
282354 break ;
283355 }
284356
285- this . _localCleanup = dispose ( this . _localCleanup ) ;
286-
287357 // update label and show
288358 let text = strings . format ( '({0}/{1}) ' , this . _model . indexOf ( marker ) + 1 , this . _model . length ( ) ) ;
289359 if ( marker . source ) {
@@ -292,62 +362,10 @@ class MarkerNavigationWidget extends ZoneWidget {
292362 dom . clearNode ( this . _element ) ;
293363 this . _element . appendChild ( document . createTextNode ( text ) ) ;
294364 this . _element . appendChild ( renderHtml ( marker . message ) ) ;
295- this . _quickFixSection . style . display = 'none' ;
296-
297- getCodeActions ( this . editor . getModel ( ) , Range . lift ( marker ) ) . then ( result => {
298- dom . clearNode ( this . _quickFixSection ) ;
299-
300- if ( result . length > 0 ) {
301-
302- this . _localCleanup . push ( {
303- dispose : ( ) => {
304- this . _quickFixEntries = [ ] ;
305- }
306- } ) ;
307-
308- let quickfixhead = document . createElement ( 'span' ) ;
309- quickfixhead . className = 'quickfixhead' ;
310- quickfixhead . appendChild ( document . createTextNode ( result . length > 1 ? nls . localize ( 'quickfix.multiple.label' , 'Suggested fixes: ' ) : nls . localize ( 'quickfix.single.label' , 'Suggested fix: ' ) ) ) ;
311- this . _quickFixSection . appendChild ( quickfixhead ) ;
312-
313- this . _quickFixEntries = [ ] ;
314- let quickfixcontainer = document . createElement ( 'span' ) ;
315- quickfixcontainer . className = 'quickfixcontainer' ;
316- result . forEach ( ( fix , idx , arr ) => {
317- var container = quickfixcontainer ;
318- if ( idx > 0 ) {
319- let separator = document . createElement ( 'span' ) ;
320- separator . appendChild ( document . createTextNode ( ', ' ) ) ;
321- container . appendChild ( separator ) ;
322- }
323-
324- let entry = document . createElement ( 'a' ) ;
325- entry . tabIndex = 0 ;
326- entry . className = 'quickfixentry' ;
327- entry . appendChild ( document . createTextNode ( fix . command . title ) ) ;
328- this . _localCleanup . push ( dom . addDisposableListener ( entry , dom . EventType . CLICK , ( ) => {
329- this . _keybindingService . executeCommand ( fix . command . id , ...fix . command . arguments ) ;
330- return true ;
331- } ) ) ;
332- this . _localCleanup . push ( dom . addStandardDisposableListener ( entry , 'keydown' , ( e ) => {
333- switch ( e . asKeybinding ( ) ) {
334- case CommonKeybindings . ENTER :
335- case CommonKeybindings . SPACE :
336- this . _keybindingService . executeCommand ( fix . command . id , ...fix . command . arguments ) ;
337- e . preventDefault ( ) ;
338- e . stopPropagation ( ) ;
339- }
340- } ) ) ;
341- container . appendChild ( entry ) ;
342-
343- this . _quickFixEntries . push ( entry ) ;
344- } ) ;
345- this . _quickFixSection . appendChild ( quickfixcontainer ) ;
346-
347- this . _quickFixSection . style . display = '' ;
348- this . show ( new Position ( marker . startLineNumber , marker . startColumn ) , 4 ) ;
349- }
350- } , onUnexpectedError ) ;
365+
366+ this . _fixesWidget
367+ . update ( getCodeActions ( this . editor . getModel ( ) , Range . lift ( marker ) ) )
368+ . then ( ( ) => this . show ( new Position ( marker . startLineNumber , marker . startColumn ) , 4 ) ) ;
351369
352370 this . _model . withoutWatchingEditorPosition ( ( ) => this . show ( new Position ( marker . startLineNumber , marker . startColumn ) , 3 ) ) ;
353371 }
0 commit comments