@@ -143,3 +143,69 @@ export class MruTracker {
143
143
export function tsDisplayPartsToText ( parts : ts . SymbolDisplayPart [ ] ) : string {
144
144
return parts . map ( dp => dp . text ) . join ( '' ) ;
145
145
}
146
+
147
+ interface DocumentPosition {
148
+ fileName : string ;
149
+ pos : number ;
150
+ }
151
+
152
+ /**
153
+ *
154
+ * This function attempts to use *internal* TypeScript APIs to find the original source spans for
155
+ * the `ts.DefinitionInfo` using source maps. If it fails, this function returns the same
156
+ * `ts.DefinitionInfo` that was passed in.
157
+ *
158
+ * @see https://github.com/angular/vscode-ng-language-service/issues/1588
159
+ */
160
+ export function getMappedDefinitionInfo (
161
+ info : ts . DefinitionInfo , project : ts . server . Project ) : ts . DefinitionInfo {
162
+ try {
163
+ const mappedDocumentSpan = getMappedDocumentSpan ( info , project ) ;
164
+ return { ...info , ...mappedDocumentSpan } ;
165
+ } catch {
166
+ return info ;
167
+ }
168
+ }
169
+
170
+ function getMappedDocumentSpan (
171
+ documentSpan : ts . DocumentSpan , project : ts . server . Project ) : ts . DocumentSpan | undefined {
172
+ const newPosition = getMappedLocation ( documentSpanLocation ( documentSpan ) , project ) ;
173
+ if ( ! newPosition ) return undefined ;
174
+ return {
175
+ fileName : newPosition . fileName ,
176
+ textSpan : { start : newPosition . pos , length : documentSpan . textSpan . length } ,
177
+ originalFileName : documentSpan . fileName ,
178
+ originalTextSpan : documentSpan . textSpan ,
179
+ contextSpan : getMappedContextSpan ( documentSpan , project ) ,
180
+ originalContextSpan : documentSpan . contextSpan
181
+ } ;
182
+ }
183
+
184
+ function getMappedLocation (
185
+ location : DocumentPosition , project : ts . server . Project ) : DocumentPosition | undefined {
186
+ const mapsTo = ( project as any ) . getSourceMapper ( ) . tryGetSourcePosition ( location ) ;
187
+ return mapsTo &&
188
+ ( project . projectService as any ) . fileExists ( ts . server . toNormalizedPath ( mapsTo . fileName ) ) ?
189
+ mapsTo :
190
+ undefined ;
191
+ }
192
+
193
+ function documentSpanLocation ( { fileName, textSpan} : ts . DocumentSpan ) : DocumentPosition {
194
+ return { fileName, pos : textSpan . start } ;
195
+ }
196
+
197
+ function getMappedContextSpan (
198
+ documentSpan : ts . DocumentSpan , project : ts . server . Project ) : ts . TextSpan | undefined {
199
+ const contextSpanStart = documentSpan . contextSpan &&
200
+ getMappedLocation ( { fileName : documentSpan . fileName , pos : documentSpan . contextSpan . start } ,
201
+ project ) ;
202
+ const contextSpanEnd = documentSpan . contextSpan &&
203
+ getMappedLocation ( {
204
+ fileName : documentSpan . fileName ,
205
+ pos : documentSpan . contextSpan . start + documentSpan . contextSpan . length
206
+ } ,
207
+ project ) ;
208
+ return contextSpanStart && contextSpanEnd ?
209
+ { start : contextSpanStart . pos , length : contextSpanEnd . pos - contextSpanStart . pos } :
210
+ undefined ;
211
+ }
0 commit comments