1
1
import * as fs from 'fs' ;
2
2
import * as ts from 'typescript' ;
3
+ import * as url from 'url' ;
3
4
4
5
import { LanguageService } from '@angular/language-service' ;
5
6
@@ -100,27 +101,22 @@ class ProjectLoggerImpl implements ProjectLogger {
100
101
}
101
102
}
102
103
103
- function removePrefix ( value : string , ...prefixes : string [ ] ) : string {
104
- for ( const prefix of prefixes ) {
105
- if ( value && value . startsWith ( prefix ) ) {
106
- return value . substr ( prefix . length ) ;
107
- }
104
+ function uriToFileName ( uri : string ) : string {
105
+ const parsedUrl = url . parse ( uri ) ;
106
+ switch ( parsedUrl . protocol ) {
107
+ case 'file:' :
108
+ case 'private:' :
109
+ return parsedUrl . path
108
110
}
109
- return value ;
110
111
}
111
112
112
- const privateProtocol = "private:" ;
113
113
const fileProtocol = "file://" ;
114
- function uriToFileName ( uri : string ) : string {
115
- return removePrefix ( decodeURI ( uri ) , fileProtocol , privateProtocol ) ;
116
- }
117
-
118
114
function fileNameToUri ( fileName : string ) : string {
119
115
return encodeURI ( fileProtocol + fileName ) ;
120
116
}
121
117
122
118
export interface NgServiceInfo {
123
- fileName : string ;
119
+ fileName ? : string ;
124
120
languageId ?: string ;
125
121
service ?: LanguageService ;
126
122
offset ?: number ;
@@ -155,17 +151,21 @@ export class TextDocuments {
155
151
connection . onDidOpenTextDocument ( event => {
156
152
// An interersting text document was opened in the client. Inform TypeScirpt's project services about it.
157
153
const file = uriToFileName ( event . textDocument . uri ) ;
158
- const { configFileName, configFileErrors } = this . projectService . openClientFile ( file , event . textDocument . text ) ;
159
- if ( configFileErrors && configFileErrors . length ) {
160
- // TODO: Report errors
161
- this . logger . msg ( `Config errors encountered and need to be reported: ${ configFileErrors . length } \n ${ configFileErrors . map ( error => error . messageText ) . join ( '\n ' ) } ` ) ;
154
+ if ( file ) {
155
+ const { configFileName, configFileErrors } = this . projectService . openClientFile ( file , event . textDocument . text ) ;
156
+ if ( configFileErrors && configFileErrors . length ) {
157
+ // TODO: Report errors
158
+ this . logger . msg ( `Config errors encountered and need to be reported: ${ configFileErrors . length } \n ${ configFileErrors . map ( error => error . messageText ) . join ( '\n ' ) } ` ) ;
159
+ }
160
+ this . languageIds . set ( event . textDocument . uri , event . textDocument . languageId ) ;
162
161
}
163
- this . languageIds . set ( event . textDocument . uri , event . textDocument . languageId ) ;
164
162
} ) ;
165
163
166
164
connection . onDidCloseTextDocument ( event => {
167
165
const file = uriToFileName ( event . textDocument . uri ) ;
168
- this . projectService . closeClientFile ( file ) ;
166
+ if ( file ) {
167
+ this . projectService . closeClientFile ( file ) ;
168
+ }
169
169
} ) ;
170
170
171
171
connection . onDidChangeTextDocument ( event => {
@@ -195,16 +195,21 @@ export class TextDocuments {
195
195
// If the file is saved, force the content to be reloaded from disk as the content might have changed on save.
196
196
this . changeNumber ++ ;
197
197
const file = uriToFileName ( event . textDocument . uri ) ;
198
- const savedContent = this . host . readFile ( file ) ;
199
- this . projectService . closeClientFile ( file ) ;
200
- this . projectService . openClientFile ( file , savedContent ) ;
201
- this . changeNumber ++ ;
198
+ if ( file ) {
199
+ const savedContent = this . host . readFile ( file ) ;
200
+ this . projectService . closeClientFile ( file ) ;
201
+ this . projectService . openClientFile ( file , savedContent ) ;
202
+ this . changeNumber ++ ;
203
+ }
202
204
} ) ;
203
205
}
204
206
205
207
public offsetsToPositions ( document : TextDocumentIdentifier , offsets : number [ ] ) : Position [ ] {
206
208
const file = uriToFileName ( document . uri ) ;
207
- return this . projectService . positionsToLineOffsets ( file , offsets ) . map ( lineOffset => Position . create ( lineOffset . line - 1 , lineOffset . col - 1 ) ) ;
209
+ if ( file ) {
210
+ return this . projectService . positionsToLineOffsets ( file , offsets ) . map ( lineOffset => Position . create ( lineOffset . line - 1 , lineOffset . col - 1 ) ) ;
211
+ }
212
+ return [ ] ;
208
213
}
209
214
210
215
public getNgService ( document : TextDocumentIdentifier ) : LanguageService | undefined {
@@ -213,18 +218,20 @@ export class TextDocuments {
213
218
214
219
public getServiceInfo ( document : TextDocumentIdentifier , position ?: Position ) : NgServiceInfo {
215
220
const fileName = uriToFileName ( document . uri ) ;
216
- const project = this . projectService . getProjectForFile ( fileName ) ;
217
- const languageId = this . languageIds . get ( document . uri ) ;
218
- if ( project ) {
219
- const service = project . compilerService . ngService ;
220
- if ( position ) {
221
- // VSCode is 0 based, editor services are 1 based.
222
- const offset = this . projectService . lineOffsetsToPositions ( fileName , [ { line : position . line + 1 , col : position . character + 1 } ] ) [ 0 ] ;
223
- return { fileName, service, offset, languageId} ;
221
+ if ( fileName ) {
222
+ const project = this . projectService . getProjectForFile ( fileName ) ;
223
+ const languageId = this . languageIds . get ( document . uri ) ;
224
+ if ( project ) {
225
+ const service = project . compilerService . ngService ;
226
+ if ( position ) {
227
+ // VSCode is 0 based, editor services are 1 based.
228
+ const offset = this . projectService . lineOffsetsToPositions ( fileName , [ { line : position . line + 1 , col : position . character + 1 } ] ) [ 0 ] ;
229
+ return { fileName, service, offset, languageId} ;
230
+ }
231
+ return { fileName, service, languageId} ;
224
232
}
225
- return { fileName, service , languageId} ;
233
+ return { fileName, languageId} ;
226
234
}
227
- return { fileName, languageId} ;
228
235
}
229
236
230
237
public ifUnchanged ( f : ( ) => void ) : ( ) => void {
0 commit comments