Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Parsing error: File 'tsconfig.json' not found" when path has any caps and is on non-system drive (C:). #1580

Closed
matracey opened this issue Feb 8, 2020 · 13 comments
Assignees
Labels
external This issue is with another package, not typescript-eslint itself package: typescript-estree Issues related to @typescript-eslint/typescript-estree working as intended Issues that are closed as they are working as intended

Comments

@matracey
Copy link

matracey commented Feb 8, 2020

What code were you trying to parse?

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true
  }
}

What did you expect to happen?
I expected the tslint.json file to be parsed and for the eslint results to be returned.

What actually happened?
I received an Parsing error: File 'tsconfig.json' not found.

I have created a repository where the issue can be easily reproduced by cloning on Windows to a drive that isn't your system drive (C: in most cases).

Versions

package version
@typescript-eslint/parser ^2.19.0
TypeScript ~3.7.5
ESLint ^6.8.0
node 13.7.0
npm 6.13.6
@matracey matracey added package: parser Issues related to @typescript-eslint/parser triage Waiting for team members to take a look labels Feb 8, 2020
@armano2
Copy link
Member

armano2 commented Feb 8, 2020

I have created a repository where the issue can be easily reproduced by cloning on Windows to a drive that isn't your system drive (C: in most cases).

can you share it?

@armano2 armano2 self-assigned this Feb 8, 2020
@armano2 armano2 added awaiting response Issues waiting for a reply from the OP or another party package: typescript-estree Issues related to @typescript-eslint/typescript-estree and removed package: parser Issues related to @typescript-eslint/parser triage Waiting for team members to take a look labels Feb 8, 2020
@matracey
Copy link
Author

matracey commented Feb 8, 2020

Sorry - forgot to add the link. https://github.com/matracey/typescript-eslint-caps-path-issue-repro

@armano2 armano2 removed the awaiting response Issues waiting for a reply from the OP or another party label Feb 8, 2020
@bradzacher bradzacher added the triage Waiting for team members to take a look label Feb 10, 2020
@armano2
Copy link
Member

armano2 commented Feb 12, 2020

Ok, i got a little busy with other stuff, but i'm on it now,

-> it's wierd i'm doing most of my tests on windows on D or E partition and usually they have some capital letters


i'v tried to reproduce this issue with repo that you provided and i don't see any issues when executing eslint in D:\Projects\typescript-eslint-caps-path-issue-repro\ANGULAR\

$ eslint . --ext .ts,.js
Tried to lint D:\Projects\typescript-eslint-caps-path-issue-repro\ANGULAR\e2e\protractor.conf.js but found no valid, enabled rules for this file type and file path in the resolved configuration.

D:\Projects\typescript-eslint-caps-path-issue-repro\ANGULAR\e2e\protractor.conf.js
  11:1   error    Expected indentation of 4 spaces but found 2       @typescript-eslint/indent
  12:1   error    Expected indentation of 4 spaces but found 2       @typescript-eslint/indent
  13:1   error    Expected indentation of 8 spaces but found 4       @typescript-eslint/indent
  14:1   error    Expected indentation of 4 spaces but found 2       @typescript-eslint/indent
  15:1   error    Expected indentation of 4 spaces but found 2       @typescript-eslint/indent

same goes for ng lint

ng lint
Linting "ng-slow-scss-repro"...
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/app/app-routing.module.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/app/app.component.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/app/app.module.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/environments/environment.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/main.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/polyfills.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.     
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/test.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/src/app/app.component.spec.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/e2e/src/app.po.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.    
Tried to lint D:/Projects/typescript-eslint-caps-path-issue-repro/ANGULAR/e2e/src/app.e2e-spec.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.
All files pass linting.
Done in 7.39s.

there can be one issue, that your path is to long, (windows by default support only 260 chars in full path), you can change this easily in group policy if you are pro/enterprise user or in registry if you have home version

@bradzacher bradzacher added awaiting response Issues waiting for a reply from the OP or another party and removed triage Waiting for team members to take a look labels Feb 12, 2020
@matracey
Copy link
Author

I don't think it's a MAX_PATH issue - my path to the tsconfig.json file is only 74 characters long. TSLint works just fine in the same folder also. As a side note, I'm running eslint using node_modules\.bin\eslint - I don't have it installed globally, but installing globally still sees the same issue.

Strangely enough, adding the --ext .ts,.js switch doesn't work for me either - I'm not matching any files.

Oops! Something went wrong! :(

ESLint: 6.8.0.

No files matching the pattern "." were found.
Please check for typing mistakes in the pattern.

I'm thinking I can try to debug the part of typescript-eslint/parser that loads the tsconfig.json file to see if I can see any reason why it isn't working. Not sure where that is right now, but I'll look through the source for it and try to debug.

@matracey
Copy link
Author

I've debugged the node_modules\.bin\eslint . command and it looks like the path to tsconfig.json is being converted to lower case at some point during executing. I'm seeing an ENOENT exception being thrown.

**handleErrorFromBinding (utils.js:230)
statSync (fs.js:948)
fileSystemEntryExists (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:5591)
fileExists (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:5603)
readFileWorker (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:5502)
readFile (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:5531)
readFile (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:100139)
watchCompilerHost.readFile (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\@typescript-eslint\typescript-estree\dist\create-program\createWatchProgram.js:183)
readFile (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:94110)
readFile (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:97319)
getParsedCommandLineOfConfigFile (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:26361)
parseConfigFile (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:100613)
createWatchProgram (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\typescript\lib\typescript.js:100288)
createWatchProgram (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\@typescript-eslint\typescript-estree\dist\create-program\createWatchProgram.js:236)
getProgramsForProjects (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\@typescript-eslint\typescript-estree\dist\create-program\createWatchProgram.js:161)
createProjectProgram (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\@typescript-eslint\typescript-estree\dist\create-program\createProjectProgram.js:20)
getProgramAndAST (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\@typescript-eslint\typescript-estree\dist\parser.js:62)
parseAndGenerateServices (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\@typescript-eslint\typescript-estree\dist\parser.js:321)
parseForESLint (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\@typescript-eslint\parser\dist\parser.js:53)
parse (e:\typescript-eslint-caps-path-issue-repro\ANGULAR\node_modules\eslint\lib\linter\linter.js:640)**

Inspecting the filePath variable at createWatchProgram.js:183, I can see its value is e:\typescript-eslint-caps-path-issue-repro\angular\tsconfig.json - note that the ANGULAR folder is lower case here. encoding is undefined, but I'm not sure if that's a problem.

@matracey
Copy link
Author

Ah, I've found the problem. In the file @typescript-eslint\typescript-estree\dist\create-program\shared.js, line 35 & 36 is the issue. Any particular reason why we'd want to normalize the file path and lowercase it when ts.sys.useCaseSensitiveFileNames is false? (Assuming this is only the case on Windows).

For some reason on my machine, running notepad e:\typescript-eslint-caps-path-issue-repro\angular\tsconfig.json gives me a "system cannot find the path specified", but running notepad c:\typescript-eslint-caps-path-issue-repro\angular\tsconfig.json opens the file in Notepad with no issue.

@matracey
Copy link
Author

Digging deeper, it looks like there was a folder-level case sensitivity feature introduced in Windows 10 in support of WSL. See this blog post for more details. I can check if the case sensitive attribute is enabled for the directory by running the command fsutil.exe file queryCaseSensitiveInfo E:\typescript-eslint-caps-path-issue-repro.

Case sensitive attribute on directory E:\typescript-eslint-caps-path-issue-repro is enabled.

In contrast, here's what I see when I run it for the same folder on my C: drive.

Case sensitive attribute on directory C:\typescript-eslint-caps-path-issue-repro is disabled.

I didn't turn this on for this folder - I actually cloned the repo directly from GitHub to this location, so it was turned on by default somehow. I can turn it off and node_modules\.bin\eslint . will work, but that doesn't seem like the right solution for this issue.

@bradzacher
Copy link
Member

Any particular reason why we'd want to normalize the file path and lowercase it when ts.sys.useCaseSensitiveFileNames is false?

On a system that respects case in file/folder names, the casing is important. So there is obvs a difference between C:\foo\bar.ts and C:\FOO\BAR.ts.

However on a system that does not respect case in file/folder names, the casing does not matter. So there is no difference between C:\foo\bar.ts and C:\FOO\BAR.ts.
In this system you don't want to force the client to send through exactly the same casing every single time - some tools normalise it before sending it in and lowercase it all, some pass it through in the input form, some pass it through in the form provided by the filesystem. If you treat each of these cases as unique files when they should be the same file, then you'll have cache misses and break everything.
So in this case, we do the same thing TS does internally - normalise the path to be all lowercase.


We can only really rely upon what node and TS tells us. If ts.sys.useCaseSensitiveFileNames tells us the system is case insensitive, then TS will treat the paths as case insensitive, and thus we must as well.
And the converse is true as well.

I'm not sure what the best solution is here.

@armano2
Copy link
Member

armano2 commented Feb 12, 2020

there is none, windows by default does not have this enabled and most tools is not going to work with this enabled, same goes for some apps,

when NTFS partition is used, you can enable case sensitivity per directory by running command in powershell,

$ fsutil.exe file setCaseSensitiveInfo "C:\foo" enable

you can also check it by running

$ fsutil.exe file queryCaseSensitiveInfo "C:\foo"

and disable it by running

$ fsutil.exe file setCaseSensitiveInfo "C:\foo" disable

that being said it's not bug in our package or typescript, but rather system configuration incompatibility.

@matracey
Copy link
Author

In this system you don't want to force the client to send through exactly the same casing every single time

I don't really understand why this would be the case. In my particular instance, I'm not specifying any path to tsconfig.json so it's being computed by the logic within typescript-eslint. If I'm working in a traditional case insensitive Windows environment, then it doesn't matter if the case of the directory is lowercase, uppercase, alternating case or whatever.

Clearly Windows is now an environment where case sensitivity is respected in some instances. I would have said the solution would be to remove this normalization process altogether as I can't see a scenario where it would be required, unless you happened to know of a scenario that says otherwise?

@armano2
Copy link
Member

armano2 commented Feb 12, 2020

@bradzacher bradzacher added external This issue is with another package, not typescript-eslint itself working as intended Issues that are closed as they are working as intended and removed awaiting response Issues waiting for a reply from the OP or another party labels Feb 12, 2020
@bradzacher
Copy link
Member

bradzacher commented Feb 12, 2020

as I can't see a scenario where it would be required

See the examples in my comment #1580 (comment)

Imagine this case. There is a file with the path in this exact case: C:\foo\bar\Baz.ts

If the user types in yarn lint C:\FOO\BAR\BAZ.ts, and we ask typescript for that file, then:

  • on a case sensitive filesystem, the casing matters deeply, so 'C:\FOO\BAR\BAZ.ts' !== 'C:\foo\bar\Baz.ts'. In this case, everything should fail, because the names do not match.
  • on a case INsensitive filesystem, the casing does not matter, so 'C:\FOO\BAR\BAZ.ts' === 'C:\foo\bar\Baz.ts'. In this case, nothing should fail, because the names match. But if we do not perform normalisation to lowercase the filenames, then it will fail, because the names will not match.

As mentioned in my comment, we cannot rely on all sources of filenames to return the same casing on a case insensitive system. So without normalisation we can and will miss the caches, causing errors when there shouldn't be.

I know, because I wrote that code. I tested this thoroughly on macos which is case insensitive. I ran into edge cases and errors and I wrote that code that mirrors what typescript does for good reason.

... some tools normalise it before sending it in and lowercase it all, some pass it through in the input form, some pass it through in the form provided by the filesystem. If you treat each of these cases as unique files when they should be the same file, then you'll have cache misses and break everything.


This isn't something to take up with us though. This is up to typescript.
We are built on top of typescript. As such we have to mirror how typescript works. If we do not, then we will miss the cache, miss files, and throw errors when we shouldn't.

As armano mentioned - there are tracking tasks in TS for this. We will always mirror TS here.

See here where TS does its checks to see if the filesystem is case sensitive. Note how they hard code the check for windows, irrespective of the filesystem settings.
https://github.com/Microsoft/TypeScript/blob/da8d3ef0a8354d5e2168c5ddc161ee65b13ccd78/src/compiler/sys.ts#L1361-L1368

@armano2
Copy link
Member

armano2 commented Feb 12, 2020

there is also rejected ticket at node about this "feature"

Is there room for a warning in node.js?
pseudo code
if(isWindows && cache.hasOwnPorperty(modulename.toLower) then console.warn ("A U sure you wish to play the casing game on windows?"

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
external This issue is with another package, not typescript-eslint itself package: typescript-estree Issues related to @typescript-eslint/typescript-estree working as intended Issues that are closed as they are working as intended
Projects
None yet
Development

No branches or pull requests

3 participants