Skip to content

Newly created project cannot lint environment.prod.ts file #17382

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

Closed
1 of 15 tasks
destus90 opened this issue Apr 3, 2020 · 7 comments · Fixed by #20291
Closed
1 of 15 tasks

Newly created project cannot lint environment.prod.ts file #17382

destus90 opened this issue Apr 3, 2020 · 7 comments · Fixed by #20291

Comments

@destus90
Copy link
Contributor

destus90 commented Apr 3, 2020

🐞 Bug report

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • xi18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

Not sure

Description

Newly created project cannot lint environment.prod.ts file. After setting "include": [ "src/**/*.ts" ] in tsconfig.app.json everything works fine.

🔬 Minimal Reproduction

Create a new project with the CLI and run this command ng lint --files src/environments/environment.prod.ts in your terminal.

🔥 Exception or Error


src\\environments\\environment.prod.ts" is not part of a TypeScript project 'tsconfig.app.json,tsconfig.spec.json,e2e/tsconfig.json

🌍 Your Environment




Angular CLI: 9.0.7
Node: 12.3.1
OS: win32 x64

Angular: 9.0.7
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.7
@angular-devkit/build-angular     0.900.7
@angular-devkit/build-optimizer   0.900.7
@angular-devkit/build-webpack     0.900.7
@angular-devkit/core              9.0.7
@angular-devkit/schematics        9.0.7
@ngtools/webpack                  9.0.7
@schematics/angular               9.0.7
@schematics/update                0.900.7
rxjs                              6.5.5
typescript                        3.7.5
webpack                           4.41.2

Anything else relevant?

@dgp1130
Copy link
Collaborator

dgp1130 commented Apr 9, 2020

Discussed in the CLI meeting and this is a bit of a tricky one, as replacement files aren't really a part of any TypeScript compilation.

For users experiencing this problem today, I think the workaround would be to include any file replacements in angular.json in the files array in tsconfig.app.json. ng lint should then run the relevant checks for that compilation unit.

The best real solution we identified is to add a migration in a major version which takes all the file replacements in angular.json and adds them to tsconfig.app.json. This would fix linting and put things into a good state. From there we would need to maintain that state going forward for user changes to angular.json. Easiest solution would be to add a warning to ng lint or ng build which detects a discrepancy between angular.json and tsconfig.app.json and prints out an error along the lines of "Please add to tsconfig.app.json files to support linting it." This would at least notify users at the right time and give them an easy opportunity to fix the problem.

It does require a user to add a change in two places instead of one. Ideally, we would have some kind of automatic fixer when this warning is triggered, but I don't think we have infra to support that at the moment. One concern here is that we're somewhat arbitrarily choosing to add to tsconfig.app.json rather than other tsconfig files. That's probably right, but some users may need to move a replacement file to a different tsconfig to enable the right lint checks.

@mgechev, how does this change with ESLint going forward? Does ESLint require its files to be part of a TypeScript compilation? Is it worth adding a migration in the next major version just to undo it in a subsequent version when we switch to ESLint?

@destus90
Copy link
Contributor Author

@dgp1130
I would like to note that this issue happens not only with the replacement files. If some .ts file is not imported anywhere in your project it can not be linted too. I have created a simple repository which demonstrates the issue: https://github.com/destus90/angular-lint-issue

@dgp1130
Copy link
Collaborator

dgp1130 commented Apr 16, 2020

Had some additional discussion on the CLI team this week as this issue gets quite tricky. Fundamentally, all dependent types are needed to lint a particular file (because many lint checks are type-aware). If a file is missing from the compilation, then those dependencies cannot be resolved intelligently and we can't effectively lint that file. This also means that ESLint won't help us here because it will suffer the same problem.

There are three specific challenges which are addressed in this particular issue:

  • Unused files cannot be linted.
  • File replacements cannot be linted.
  • ng new creates a project which includes files that cannot be linted.

Unused files cannot be linted

This is actually a TypeScript problem moreso than an Angular one. TSLint provides no means of linting files not in the project due to the aforementioned typing issues. If you create a non-Angular project with an unused file not include in tsconfig, it encounters the same problem. The only solution in that case is to include it directly in tsconfig via a glob pattern of some kind (src/**/*.ts), which we used to do and stopped in v9 because it was slowing down builds. The only options we see to fix this are:

  1. Reverse the previous decision and include src/**/*.ts.
    • This would increase build times, particularly for large projects.
    • It also doesn't work well for test files or worker files as they use different types. Maybe a solution-style tsconfig could help us here, but fundamentally we would need to make some kind of guess about the usage-pattern of an unused file. We simply don't have any effective means of inferring whether a given unused file belongs in tsconfig.app.json, tsconfig.spec.json, or anything else.
  2. Have TSLint/ESLint provide some mechanism of linting a file without it being included in a compilation.
    • This is basically a use case which TSLint/ESLint don't currently have a good story to handle. If either tool provides meaningful direction for this scenario, we can do our best to make Angular compatible with it.

File replacements cannot be linted

We previously suggested using a migration to include file replacements in tsconfig.app.json. This could cause additional problems to users if they do weird things in file replacements. For example, if environment.ts declares a global variable foo while environment.prod.ts declares a global bar. These files can lint individually, but if another file (baz.ts) depends on ./environment, it will only have foo available during linting (even though building prod would include bar). There is also the case of a file which uses worker APIs (or Jasmine test APIs) and should be included in the associated tsconfig, which won't be tsconfig.app.json.

Instead, the warning on its own may be the best for now. This warning can iterate over file replacements in angular.json and verify that they are in the files list of a tsconfig file. If not, it will inform users to add the replacement to the relevant tsconfig.*.json. We may also need some documentation to help the user identify which tsconfig a given file should be included in.

Longer term, we should evaluate an alternative to file replacements, as it is some weird Angular magic that confuses the compiler/linter. If we could support multi-build use cases without rewriting imports, we could make this play much better with the compiler/linter. I'm thinking something similar to what https://dagger.dev/ does by injecting an interface and deferring the decision of importing a module to the very top-level main function, then generating a dev/prod version of that. We could also generate a tsconfig specifically for linting, and use a default tsconfig for file replacements (similar to what the language service does). This is quite a complex problem, and I don't want to try and solve it here, but there are potentially ways of doing this that would work better with the compiler and linter.

ng new creates a project which includes files that cannot be linted

ng new should create a well-formed project. Fortunately this is the easiest to address as we can update the schematic to include environment.prod.ts in tsconfig.app.json. That should make ng lint work out of the box, and the warning will help application developers keep it that way.

@dgp1130 dgp1130 removed the needs: discussion On the agenda for team meeting to determine next steps label Apr 23, 2020
@alan-agius4 alan-agius4 self-assigned this Jul 14, 2020
@dominikfoldi
Copy link

dominikfoldi commented Sep 8, 2020

After I add the src/environment/environment.prod.ts to the files array in my tsconfig.app.json, then I get the following warning when I build my Angular project in prod mode:

WARNING in ...\src\environments\environment.prod.ts is part of the TypeScript compilation but it's unused.
Add only entry points to the 'files' or 'include' properties in your tsconfig.

Is there any workaround for hiding this warning but make the linting work at the same time?

@TokenR1ng
Copy link

Any news on this one? We face the same problem where we have files that are only included (imported) when run/build with a specific environment by exporting them in the respective environment file. So those TS files look "unused" to the compilation and we get the same warning on the build. However, we need those file to be compiled as well to check for any errors.

@krzyhan
Copy link

krzyhan commented Feb 15, 2021

After I add the src/environment/environment.prod.ts to the files array in my tsconfig.app.json, then I get the following warning when I build my Angular project in prod mode:

WARNING in ...\src\environments\environment.prod.ts is part of the TypeScript compilation but it's unused.
Add only entry points to the 'files' or 'include' properties in your tsconfig.

Is there any workaround for hiding this warning but make the linting work at the same time?

you can change tsconfig.app.json

"include": ["src/**/*.d.ts", "src/environments/*.ts"],

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Apr 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.