match leading slash imports with path mappings - fixes #13730#27980
match leading slash imports with path mappings - fixes #13730#27980sheetalkamat merged 1 commit intomicrosoft:masterfrom
Conversation
| } | ||
| /* @internal */ | ||
| namespace ts { | ||
| export function startsWithSlash(name: string) { |
There was a problem hiding this comment.
Since this function is not used anywhere else, you could avoid exporting it
There was a problem hiding this comment.
Great tip. I tried that first, but I had some trouble which seemed to be caused by the /* internal */ comment, it could not resolve CharacterCodes. I just tried to move it again, and now it works. My knowledge of TypeScript is very low, so I will adjust it.
|
Question for the maintainers: do you guys want me to squash the commits once the code has stabilized? |
|
@sheetalkamat I have made some changes:
|
|
There is one potential problem left. When thinking about this problem it is important to remember that the function Before this change, all With this change, all This is not necessarily a problem. However, in some code bases there is 'invisible' coupling between concepts. The coupling for this case would be the assumption that As far as I can tell (by tracing back the introduction of path mapping and the introduction of root path's as 'relative') any coupling that exist would be accidental. I can also imagine that if a developer used Looking at the uses of
My advise would be to create a separate issue to track down the uses of
|
2c8642e to
82e9ef7
Compare
|
I have squashed the commits. |
|
@sheetalkamat What's next? |
| if (state.traceEnabled) { | ||
| trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); | ||
| } | ||
| if (paths) { |
There was a problem hiding this comment.
I think this should be pulled out into separate function instead of inlining. Its easier to read.
We also need trace above this line about using baseUrl in that.
There was a problem hiding this comment.
I think this should be pulled out into separate function instead of inlining.
I thought about that. I however couldn't think of a name. The name tryLoadModuleUsingPaths is already taken. What do you suggest?
We also need trace above this line about using baseUrl in that.
The trace baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1 is not exactly correct for what is happening. And since we have the trace paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0 I thought that would be enough. But if you really want it there I could of course add it back in.
There was a problem hiding this comment.
Yes please add that back in there since its used in there anyways.
| function isEligibleForPathMapping(moduleName: string, paths: MapLike<string[]>): boolean { | ||
| if (isRootedDiskPath(moduleName) || isUrl(moduleName)) { | ||
| // check for potential alias otherwise { '*': './src/*' } will match | ||
| const root = moduleName.slice(0, getRootLength(moduleName)); |
There was a problem hiding this comment.
You don't need all these checks. The path mapping needs to be done if: moduleName is not relative path or it is absolute path.
There was a problem hiding this comment.
Did you read the comment?
It would break backwards compatibility and existing configurations.
There was a problem hiding this comment.
@DanielRosenwasser isn't this change expected breaking change ?
There was a problem hiding this comment.
Yes, I thought that was the point of this PR in the first place. What exactly are the extra checks meant to protect against?
There was a problem hiding this comment.
Root (or url) imports failing (resolving to another file) in existing projects failing because they have a * mapping.
There was a problem hiding this comment.
As mentioned this is desired to be a breaking change. Please remove these extra checks
| if (resolved) return resolved.value; | ||
| } | ||
|
|
||
| if (!isExternalModuleNameRelative(moduleName)) { |
There was a problem hiding this comment.
Also needs some tests to ensure that caching is working as intended (and hasn't changed)
There was a problem hiding this comment.
Could you point me in the right direction? I am unsure what would be needed.
There was a problem hiding this comment.
There are tests in src/testRunner/moduleResolution.ts that verify caching is working as expected.
There was a problem hiding this comment.
@sheetalkamat Can you please explain how I can run the unit tests? Thank you
There was a problem hiding this comment.
@sheetalkamat I figured it out, they are run by default
|
Also need changes in |
What kind of inputs would this fail on? |
|
More than failing of completions, we need to make sure the path completions are correct when there is path mapping. |
a361e89 to
340bb87
Compare
|
@sheetalkamat I have updated the code to reflect your comments (apart from the ones that still have questions). I also squashed my commits again and rebased on master. Could you please take another look? |
| if (isRootedDiskPath(moduleName) || isUrl(moduleName)) { | ||
| // check for potential alias otherwise { '*': './src/*' } will match | ||
| const root = moduleName.slice(0, getRootLength(moduleName)); | ||
| const potentialAlias = getOwnKeys(paths).find(path => path.startsWith(root)); |
There was a problem hiding this comment.
find and startsWith are ES2015 and we support ES5 environments, so use the helper functions from core.ts
| // check for potential alias otherwise { '*': './src/*' } will match | ||
| const root = moduleName.slice(0, getRootLength(moduleName)); | ||
| const potentialAlias = getOwnKeys(paths).find(path => path.startsWith(root)); | ||
| return Boolean(potentialAlias); |
340bb87 to
aadfa61
Compare
| if (compilerOptions.rootDirs) { | ||
| return getCompletionEntriesForDirectoryFragmentWithRootDirs( | ||
| compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath); | ||
| if (isRootedDiskPath(literalValue) || isUrl(literalValue)) { |
| compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath); | ||
| if (isRootedDiskPath(literalValue) || isUrl(literalValue)) { | ||
| if (compilerOptions.baseUrl) { | ||
| return getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, compilerOptions, host, typeChecker); |
There was a problem hiding this comment.
The two getCompletionEntriesForNonRelativeModules calls are identical, as are the two getCompletionEntriesForRelativeModules calls. This could be a single conditional instead of several nested ones.
return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && (isRootedDiskPath(literalValue) || isUrl(literalValue))
? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath)
: getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, compilerOptions, host, typeChecker);aadfa61 to
1a9c209
Compare
|
@sheetalkamat I have made the required changes. |
sheetalkamat
left a comment
There was a problem hiding this comment.
What is the change in tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter ?? Please revert it. Thanks
|
@sheetalkamat Those are really difficult to revert -- it happens when the submodule is updated by git. I think it's fine because we regularly update these anyway. |
|
@EECOLOR thank you for contribution. This should be available in tonight's nightly build. |
|
@sheetalkamat thank you and your team for your help |
|
@sheetalkamat did something go wrong with the nightly build? |
|
@weswigham @DanielRosenwasser would know. |
|
Looks like for some reason the nightly publish job didn't get scheduled until I just went to go check on the task. Likely an azure devops issue - since I believe it just triggered, we'll probably publish a nightly in about 30 minutes. |
Checklist:
masterbranchjake runtestslocallyAbout the code changes: I can imagine you would like to have the code structured differently or have different traces. I just looked at what currently been implemented and took the most straightforward approach making the changes easy to diff. Feel free to make suggestions.
About the tests: I am missing information to provide the correct amount of tests, or actually I don't know what your policy is. I think the tests I added should cover all of the code I added and prevent future breakage.
About performance: I tried to minimize the performance impact. I am not sure how often this code is called in situations where high performance is required. That said, I noticed a lot of places where performance could be improved, so I am not sure how much you guys want to focus on that.
About caching: I noticed a few places where
isExternalModuleNameRelativeis used in relation to caching. We might want to add the 'is potentially an alias import' there as well. This however requires some extra thought. An example of such a place:Fixes #13730