@@ -141,29 +141,7 @@ abstract class PathString extends string {
141
141
* components of this path refers to when resolved relative to the
142
142
* given `root` folder.
143
143
*/
144
- Path resolveUpTo ( int n , Folder root ) {
145
- n = 0 and result .getContainer ( ) = root and root = getARootFolder ( )
146
- or
147
- exists ( Path base , string next | next = getComponent ( this , n - 1 , base , root ) |
148
- // handle empty components and the special "." folder
149
- ( next = "" or next = "." ) and
150
- result = base
151
- or
152
- // handle the special ".." folder
153
- next = ".." and result = base .( ConsPath ) .getParent ( )
154
- or
155
- // special handling for Windows drive letters when resolving absolute path:
156
- // the extractor populates "C:/" as a folder that has path "C:/" but name ""
157
- n = 1 and
158
- next .regexpMatch ( "[A-Za-z]:" ) and
159
- root .getBaseName ( ) = "" and
160
- root .toString ( ) = next .toUpperCase ( ) + "/" and
161
- result = base
162
- or
163
- // default case
164
- result = TConsPath ( base , next )
165
- )
166
- }
144
+ Path resolveUpTo ( int n , Folder root ) { result = resolveUpTo ( this , n , root , _) }
167
145
168
146
/**
169
147
* Gets the absolute path that this path refers to when resolved relative to
@@ -172,16 +150,57 @@ abstract class PathString extends string {
172
150
Path resolve ( Folder root ) { result = resolveUpTo ( getNumComponent ( ) , root ) }
173
151
}
174
152
153
+ /**
154
+ * Gets the absolute path that the sub-path consisting of the first `n`
155
+ * components of this path refers to when resolved relative to the
156
+ * given `root` folder.
157
+ */
158
+ private Path resolveUpTo ( PathString p , int n , Folder root , boolean inTS ) {
159
+ n = 0 and result .getContainer ( ) = root and root = p .getARootFolder ( ) and inTS = false
160
+ or
161
+ exists ( Path base , string next | next = getComponent ( p , n - 1 , base , root , inTS ) |
162
+ // handle empty components and the special "." folder
163
+ ( next = "" or next = "." ) and
164
+ result = base
165
+ or
166
+ // handle the special ".." folder
167
+ next = ".." and result = base .( ConsPath ) .getParent ( )
168
+ or
169
+ // special handling for Windows drive letters when resolving absolute path:
170
+ // the extractor populates "C:/" as a folder that has path "C:/" but name ""
171
+ n = 1 and
172
+ next .regexpMatch ( "[A-Za-z]:" ) and
173
+ root .getBaseName ( ) = "" and
174
+ root .toString ( ) = next .toUpperCase ( ) + "/" and
175
+ result = base
176
+ or
177
+ // default case
178
+ result = TConsPath ( base , next )
179
+ )
180
+ }
181
+
175
182
/**
176
183
* Gets the `i`th component of the path `str`, where `base` is the resolved path one level up.
177
184
* Supports that the root directory might be compiled output from TypeScript.
185
+ * `inTS` is true if the result is TypeScript that is compiled into the path specified by `str`.
178
186
*/
179
- private string getComponent ( PathString str , int n , Path base , Folder root ) {
180
- base = str .resolveUpTo ( n , root ) and
181
- (
182
- result = str .getComponent ( n )
183
- or
184
- result = TypeScriptOutDir:: getOriginalTypeScriptFolder ( str .getComponent ( n ) , base .getContainer ( ) )
187
+ private string getComponent ( PathString str , int n , Path base , Folder root , boolean inTS ) {
188
+ exists ( boolean prevTS |
189
+ base = resolveUpTo ( str , n , root , prevTS ) and
190
+ (
191
+ result = str .getComponent ( n ) and prevTS = inTS
192
+ or
193
+ // If we are in a TypeScript source folder, try to replace file endings with ".ts" or ".tsx"
194
+ n = str .getNumComponent ( ) - 1 and
195
+ prevTS = true and
196
+ inTS = prevTS and
197
+ result = str .getComponent ( n ) .regexpCapture ( "^(.*)\\.js$" , 1 ) + "." + [ "ts" , "tsx" ]
198
+ or
199
+ prevTS = false and
200
+ inTS = true and
201
+ result =
202
+ TypeScriptOutDir:: getOriginalTypeScriptFolder ( str .getComponent ( n ) , base .getContainer ( ) )
203
+ )
185
204
)
186
205
}
187
206
@@ -194,21 +213,35 @@ private module TypeScriptOutDir {
194
213
*/
195
214
string getOriginalTypeScriptFolder ( string outdir , Folder parent ) {
196
215
exists ( JSONObject tsconfig |
197
- tsconfig .getFile ( ) .getBaseName ( ) = "tsconfig.json" and
198
- tsconfig .isTopLevel ( ) and
199
- tsconfig .getFile ( ) .getParentContainer ( ) = parent
200
- |
201
- outdir =
202
- tsconfig
203
- .getPropValue ( "compilerOptions" )
204
- .( JSONObject )
205
- .getPropValue ( "outDir" )
206
- .( JSONString )
207
- .getValue ( ) and
208
- result = getEffectiveRootDirFromTSConfig ( tsconfig )
216
+ outdir = removeLeadingSlash ( getOutDir ( tsconfig , parent ) ) and
217
+ result = removeLeadingSlash ( getEffectiveRootDirFromTSConfig ( tsconfig ) )
209
218
)
210
219
}
211
220
221
+ /**
222
+ * Removes a leading dot and/or slash from `raw`.
223
+ */
224
+ bindingset [ raw]
225
+ private string removeLeadingSlash ( string raw ) {
226
+ result = raw .regexpCapture ( "^\\.?/?([\\w.\\-]+)$" , 1 )
227
+ }
228
+
229
+ /**
230
+ * Gets the `outDir` option from a tsconfig file from the folder `parent`.
231
+ */
232
+ private string getOutDir ( JSONObject tsconfig , Folder parent ) {
233
+ tsconfig .getFile ( ) .getBaseName ( ) .regexpMatch ( "tsconfig.*\\.json" ) and
234
+ tsconfig .isTopLevel ( ) and
235
+ tsconfig .getFile ( ) .getParentContainer ( ) = parent and
236
+ result =
237
+ tsconfig
238
+ .getPropValue ( "compilerOptions" )
239
+ .( JSONObject )
240
+ .getPropValue ( "outDir" )
241
+ .( JSONString )
242
+ .getValue ( )
243
+ }
244
+
212
245
/**
213
246
* Gets the directory that contains the TypeScript source files.
214
247
* Based on the tsconfig.json file `tsconfig`.
0 commit comments