55'use strict' ;
66
77import { workspace , Uri , EventEmitter , Disposable , TextDocument } from 'vscode' ;
8- import { LanguageClient , RequestType } from 'vscode-languageclient' ;
9-
8+ import { LanguageClient , RequestType , NotificationType } from 'vscode-languageclient' ;
9+ import { getEmbeddedContentUri , getEmbeddedLanguageId , getHostDocumentUri , isEmbeddedContentUri , EMBEDDED_CONTENT_SCHEME } from './embeddedContentUri' ;
1010
1111interface EmbeddedContentParams {
1212 uri : string ;
@@ -23,12 +23,21 @@ namespace EmbeddedContentRequest {
2323}
2424
2525export interface EmbeddedDocuments extends Disposable {
26- getVirtualDocumentUri : ( parentDocumentUri : string , embeddedLanguageId : string ) => Uri ;
27- openVirtualDocument : ( embeddedContentUri : Uri , expectedVersion : number ) => Thenable < TextDocument > ;
26+ getEmbeddedContentUri : ( parentDocumentUri : string , embeddedLanguageId : string ) => Uri ;
27+ openEmbeddedContentDocument : ( embeddedContentUri : Uri , expectedVersion : number ) => Thenable < TextDocument > ;
28+ }
29+
30+ interface EmbeddedContentChangedParams {
31+ uri : string ;
32+ version : number ;
33+ embeddedLanguageIds : string [ ] ;
2834}
2935
36+ namespace EmbeddedContentChangedNotification {
37+ export const type : NotificationType < EmbeddedContentChangedParams > = { get method ( ) { return 'embedded/contentchanged' ; } } ;
38+ }
3039
31- export function initializeEmbeddedContentDocuments ( embeddedScheme : string , client : LanguageClient ) : EmbeddedDocuments {
40+ export function initializeEmbeddedContentDocuments ( parentDocumentSelector : string [ ] , embeddedLanguages : { [ languageId : string ] : boolean } , client : LanguageClient ) : EmbeddedDocuments {
3241 let toDispose : Disposable [ ] = [ ] ;
3342
3443 let embeddedContentChanged = new EventEmitter < Uri > ( ) ;
@@ -38,16 +47,16 @@ export function initializeEmbeddedContentDocuments(embeddedScheme: string, clien
3847
3948 // documents are closed after a time out or when collected.
4049 toDispose . push ( workspace . onDidCloseTextDocument ( d => {
41- if ( d . uri . scheme === embeddedScheme ) {
50+ if ( isEmbeddedContentUri ( d . uri ) ) {
4251 delete openVirtualDocuments [ d . uri . toString ( ) ] ;
4352 }
4453 } ) ) ;
4554
4655 // virtual document provider
47- toDispose . push ( workspace . registerTextDocumentContentProvider ( embeddedScheme , {
56+ toDispose . push ( workspace . registerTextDocumentContentProvider ( EMBEDDED_CONTENT_SCHEME , {
4857 provideTextDocumentContent : uri => {
49- if ( uri . scheme === embeddedScheme ) {
50- let contentRequestParms = { uri : getParentDocumentUri ( uri ) , embeddedLanguageId : getEmbeddedLanguageId ( uri ) } ;
58+ if ( isEmbeddedContentUri ( uri ) ) {
59+ let contentRequestParms = { uri : getHostDocumentUri ( uri ) , embeddedLanguageId : getEmbeddedLanguageId ( uri ) } ;
5160 return client . sendRequest ( EmbeddedContentRequest . type , contentRequestParms ) . then ( content => {
5261 if ( content ) {
5362 openVirtualDocuments [ uri . toString ( ) ] = content . version ;
@@ -63,19 +72,16 @@ export function initializeEmbeddedContentDocuments(embeddedScheme: string, clien
6372 onDidChange : embeddedContentChanged . event
6473 } ) ) ;
6574
66- function getVirtualDocumentUri ( parentDocumentUri : string , embeddedLanguageId : string ) {
67- return Uri . parse ( embeddedScheme + '://' + embeddedLanguageId + '/' + encodeURIComponent ( parentDocumentUri ) + '.' + embeddedLanguageId ) ;
68- } ;
69-
70- function getParentDocumentUri ( virtualDocumentUri : Uri ) : string {
71- let languageId = virtualDocumentUri . authority ;
72- let path = virtualDocumentUri . path . substring ( 1 , virtualDocumentUri . path . length - languageId . length - 1 ) ; // remove leading '/' and new file extension
73- return decodeURIComponent ( path ) ;
74- } ;
75-
76- function getEmbeddedLanguageId ( virtualDocumentUri : Uri ) : string {
77- return virtualDocumentUri . authority ;
78- }
75+ // diagnostics for embedded contents
76+ client . onNotification ( EmbeddedContentChangedNotification . type , p => {
77+ for ( let languageId in embeddedLanguages ) {
78+ if ( p . embeddedLanguageIds . indexOf ( languageId ) !== - 1 ) {
79+ // open the document so that validation is triggered in the embedded mode
80+ let virtualUri = getEmbeddedContentUri ( p . uri , languageId ) ;
81+ openEmbeddedContentDocument ( virtualUri , p . version ) ;
82+ }
83+ }
84+ } ) ;
7985
8086 function ensureContentUpdated ( virtualURI : Uri , expectedVersion : number ) {
8187 let virtualURIString = virtualURI . toString ( ) ;
@@ -94,7 +100,7 @@ export function initializeEmbeddedContentDocuments(embeddedScheme: string, clien
94100 return Promise . resolve ( ) ;
95101 } ;
96102
97- function openVirtualDocument ( virtualURI : Uri , expectedVersion : number ) : Thenable < TextDocument > {
103+ function openEmbeddedContentDocument ( virtualURI : Uri , expectedVersion : number ) : Thenable < TextDocument > {
98104 return ensureContentUpdated ( virtualURI , expectedVersion ) . then ( _ => {
99105 return workspace . openTextDocument ( virtualURI ) . then ( document => {
100106 if ( expectedVersion === openVirtualDocuments [ virtualURI . toString ( ) ] ) {
@@ -106,8 +112,8 @@ export function initializeEmbeddedContentDocuments(embeddedScheme: string, clien
106112 } ;
107113
108114 return {
109- getVirtualDocumentUri ,
110- openVirtualDocument ,
115+ getEmbeddedContentUri ,
116+ openEmbeddedContentDocument ,
111117 dispose : Disposable . from ( ...toDispose ) . dispose
112118 } ;
113119
0 commit comments