@@ -18,6 +18,10 @@ import {IJSONContributionRegistry, Extensions, ISchemaContributions} from 'vs/pl
1818import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
1919import { LanguageConfigurationRegistry , LanguageConfiguration } from 'vs/editor/common/modes/languageConfigurationRegistry' ;
2020import { wireCancellationToken } from 'vs/base/common/async' ;
21+ import { IDisposable } from 'vs/base/common/lifecycle' ;
22+ import { IModelService } from 'vs/editor/common/services/modelService' ;
23+ import { onUnexpectedError } from 'vs/base/common/errors' ;
24+ import { IMarkerService } from 'vs/platform/markers/common/markers' ;
2125
2226export class JSONMode extends AbstractMode {
2327
@@ -47,11 +51,14 @@ export class JSONMode extends AbstractMode {
4751
4852 private _modeWorkerManager : ModeWorkerManager < jsonWorker . JSONWorker > ;
4953 private _threadService :IThreadService ;
54+ private _validationHelper :ValidationHelper ;
5055
5156 constructor (
5257 descriptor :modes . IModeDescriptor ,
5358 @IInstantiationService instantiationService : IInstantiationService ,
54- @IThreadService threadService : IThreadService
59+ @IThreadService threadService : IThreadService ,
60+ @IModelService modelService : IModelService ,
61+ @IMarkerService markerService : IMarkerService
5562 ) {
5663 super ( descriptor . id ) ;
5764 this . _modeWorkerManager = new ModeWorkerManager < jsonWorker . JSONWorker > ( descriptor , 'vs/languages/json/common/jsonWorker' , 'JSONWorker' , null , instantiationService ) ;
@@ -97,6 +104,18 @@ export class JSONMode extends AbstractMode {
97104 return wireCancellationToken ( token , this . _provideCompletionItems ( model . uri , position ) ) ;
98105 }
99106 } , true ) ;
107+
108+ if ( modelService && markerService ) {
109+ this . _validationHelper = new ValidationHelper ( modelService , this . getId ( ) , ( uris ) => {
110+ this . _validate ( uris ) . then ( ( result ) => {
111+ result . forEach ( r => {
112+ markerService . changeOne ( this . getId ( ) , r . resource , r . markerData ) ;
113+ } ) ;
114+ } , onUnexpectedError ) ;
115+ } ) ;
116+ } else {
117+ this . _validationHelper = null ;
118+ }
100119 }
101120
102121 public creationDone ( ) : void {
@@ -121,14 +140,17 @@ export class JSONMode extends AbstractMode {
121140
122141 public configure ( options :any ) : WinJS . TPromise < void > {
123142 if ( this . _threadService . isInMainThread ) {
124- return this . _configureWorkers ( options ) ;
143+ if ( this . _validationHelper ) {
144+ this . _validationHelper . validateAll ( ) ;
145+ }
146+ return this . _configureWorker ( options ) ;
125147 } else {
126148 return this . _worker ( ( w ) => w . _doConfigure ( options ) ) ;
127149 }
128150 }
129151
130- static $_configureWorkers = CompatWorkerAttr ( JSONMode , JSONMode . prototype . _configureWorkers ) ;
131- private _configureWorkers ( options :any ) : WinJS . TPromise < void > {
152+ static $_configureWorker = CompatWorkerAttr ( JSONMode , JSONMode . prototype . _configureWorker ) ;
153+ private _configureWorker ( options :any ) : WinJS . TPromise < void > {
132154 return this . _worker ( ( w ) => w . _doConfigure ( options ) ) ;
133155 }
134156
@@ -137,6 +159,11 @@ export class JSONMode extends AbstractMode {
137159 return this . _worker ( ( w ) => w . setSchemaContributions ( data ) ) ;
138160 }
139161
162+ static $_validate = CompatWorkerAttr ( JSONMode , JSONMode . prototype . _validate ) ;
163+ private _validate ( uris :URI [ ] ) : WinJS . TPromise < jsonWorker . ValidationResult [ ] > {
164+ return this . _worker ( ( w ) => w . validate ( uris ) ) ;
165+ }
166+
140167 static $navigateValueSet = CompatWorkerAttr ( JSONMode , JSONMode . prototype . navigateValueSet ) ;
141168 public navigateValueSet ( resource :URI , position :editorCommon . IRange , up :boolean ) :WinJS . TPromise < modes . IInplaceReplaceSupportResult > {
142169 return this . _worker ( ( w ) => w . navigateValueSet ( resource , position , up ) ) ;
@@ -166,4 +193,60 @@ export class JSONMode extends AbstractMode {
166193 public _provideDocumentRangeFormattingEdits ( resource :URI , range :editorCommon . IRange , options :modes . FormattingOptions ) :WinJS . TPromise < editorCommon . ISingleEditOperation [ ] > {
167194 return this . _worker ( ( w ) => w . format ( resource , range , options ) ) ;
168195 }
169- }
196+ }
197+
198+ class ValidationHelper {
199+
200+ private _disposables : IDisposable [ ] = [ ] ;
201+ private _listener : { [ uri : string ] : IDisposable } = Object . create ( null ) ;
202+
203+ constructor (
204+ private _modelService : IModelService ,
205+ private _selector : string ,
206+ private _validate :( what :URI [ ] ) => void
207+ ) {
208+ const onModelAdd = ( model : editorCommon . IModel ) : void => {
209+ if ( model . getModeId ( ) !== _selector ) {
210+ return ;
211+ }
212+
213+ let handle : number ;
214+ this . _listener [ model . uri . toString ( ) ] = model . onDidChangeContent ( ( ) => {
215+ clearTimeout ( handle ) ;
216+ handle = setTimeout ( ( ) => this . _validate ( [ model . uri ] ) , 500 ) ;
217+ } ) ;
218+
219+ handle = setTimeout ( ( ) => this . _validate ( [ model . uri ] ) , 500 ) ;
220+ } ;
221+
222+ const onModelRemoved = ( model : editorCommon . IModel ) : void => {
223+ delete this . _listener [ model . uri . toString ( ) ] ;
224+ } ;
225+
226+ this . _disposables . push ( this . _modelService . onModelAdded ( onModelAdd ) ) ;
227+ this . _disposables . push ( this . _modelService . onModelRemoved ( onModelRemoved ) ) ;
228+ this . _disposables . push ( this . _modelService . onModelModeChanged ( event => {
229+ onModelRemoved ( event . model ) ;
230+ onModelAdd ( event . model ) ;
231+ } ) ) ;
232+
233+ this . _disposables . push ( {
234+ dispose : ( ) => {
235+ for ( let key in this . _listener ) {
236+ this . _listener [ key ] . dispose ( ) ;
237+ }
238+ }
239+ } ) ;
240+
241+ this . _modelService . getModels ( ) . forEach ( onModelAdd ) ;
242+ }
243+
244+ public dispose ( ) : void {
245+ this . _disposables . forEach ( d => d && d . dispose ( ) ) ;
246+ this . _disposables = [ ] ;
247+ }
248+
249+ public validateAll ( ) : void {
250+ this . _validate ( Object . keys ( this . _listener ) . map ( uri => URI . parse ( uri ) ) ) ;
251+ }
252+ }
0 commit comments