fimbullinter / wotan

Pluggable TypeScript and JavaScript linter
Apache License 2.0
281 stars 23 forks source link

Wotan lints excluded files. #387

Open gustofbreak opened 6 years ago

gustofbreak commented 6 years ago

Meta

wotan 0.12.0 tsc 3.0.1

How did you run wotan? CLI

Configuration

rules:
  await-async-result:
    rule: await-async-result
    severity: error
  await-only-promise:
    rule: await-only-promise
    severity: error
  ban-dom-globals:
    rule: ban-dom-globals
    severity: error
  delete-only-optional-property:
    rule: delete-only-optional-property
    severity: error
  generator-require-yield:
    rule: generator-require-yield
    severity: error
  new-parens:
    rule: new-parens
    severity: error
  no-case-declaration:
    rule: no-case-declaration
    severity: error
  no-debugger:
    rule: no-debugger
    severity: error
  no-duplicate-case:
    rule: no-duplicate-case
    severity: error
  no-duplicate-spread-property:
    rule: no-duplicate-spread-property
    severity: error
  no-fallthrough:
    rule: no-fallthrough
    severity: error
  no-inferred-empty-object:
    rule: no-inferred-empty-object
    severity: error
  no-invalid-assertion:
    rule: no-invalid-assertion
    severity: error
  no-misused-generics:
    rule: no-misused-generics
    severity: error
  no-nan-compare:
    rule: no-nan-compare
    severity: error
  no-octal-escape:
    rule: no-octal-escape
    severity: error
  no-return-await:
    rule: no-return-await
    severity: error
  no-unassigned-variable:
    rule: no-unassigned-variable
    severity: error
  no-unreachable-code:
    rule: no-unreachable-code
    severity: error
  no-unsafe-finally:
    rule: no-unsafe-finally
    severity: error
  no-unstable-api-use:
    rule: no-unstable-api-use
    severity: error
  no-unused-expression:
    rule: no-unused-expression
    severity: error
  no-unused-label:
    rule: no-unused-label
    severity: error
  no-useless-assertion:
    rule: no-useless-assertion
    severity: 'off'
  no-useless-declare:
    rule: no-useless-declare
    severity: error
  no-useless-initializer:
    rule: no-useless-initializer
    severity: error
  no-useless-jump-label:
    rule: no-useless-jump-label
    severity: error
  no-useless-predicate:
    rule: no-useless-predicate
    severity: 'off'
  no-useless-spread:
    rule: no-useless-spread
    severity: error
  prefer-const:
    rule: prefer-const
    severity: error
  prefer-dot-notation:
    rule: prefer-dot-notation
    severity: error
  prefer-for-of:
    rule: prefer-for-of
    severity: error
  prefer-namespace-keyword:
    rule: prefer-namespace-keyword
    severity: error
  prefer-number-methods:
    rule: prefer-number-methods
    severity: error
  prefer-object-spread:
    rule: prefer-object-spread
    severity: error
  return-never-call:
    rule: return-never-call
    severity: error
  syntaxcheck:
    rule: syntaxcheck
    severity: error
  trailing-newline:
    rule: trailing-newline
    severity: error
  try-catch-return-await:
    rule: try-catch-return-await
    severity: error
  tslint/interface-name:
    options: always-prefix
    rule: interface-name
    rulesDirectories:
      -/path/to/project/root
    severity: error
  typecheck:
    rule: typecheck
    severity: error

Code

I have @types/next (with a small modification) installed at <project root>/types/next and symlink node_modules/@types/next to that path.

Running wotan ignores other node_modules fine, but it complains regarding <project root>/types/next, no matter how I set exclude in tsconfig.json.

I tried this code:

$ wotan -p ./tsconfig.json \
  -m @fimbul/heimdall # for tslint/interface-name

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "baseUrl": ".",
    "experimentalDecorators": true,
    "jsx": "preserve",
    "lib": [
      "dom",
      "es2015",
      "es2016"
    ],
    "module": "esnext",
    "moduleResolution": "node",
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "paths": {
      "~/*": ["*"]
    },
    "preserveConstEnums": true,
    "removeComments": false,
    "skipLibCheck": true,
    "sourceMap": true,
    "strictFunctionTypes": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "target": "esnext"
  },
  "exclude": [
    ".next",
    "node_modules",
    "types/next"
  ]
}

I expected to see this happen: Linting succeeds with ./types/next ignored.

Instead, this happened:

/path/to/project/types/next/index.d.ts:27:15
ERROR 27:15     tslint/interface-name  interface name must start with a capitalized I
ERROR 47:15     tslint/interface-name  interface name must start with a capitalized I
ERROR 54:15     tslint/interface-name  interface name must start with a capitalized I
ERROR 68:15     tslint/interface-name  interface name must start with a capitalized I
ERROR 76:15     tslint/interface-name  interface name must start with a capitalized I

...
ajafff commented 6 years ago

This is actually a limitation in TypeScript's API. The current implementation asks TypeScript where it would look for @types and uses these paths to exclude any matching files. These paths could be unresolved symlinks while the path of a file is typically the realpath. That's why the files are not excluded by default. Instead I would like if TypeScript could tell if a given file was found during @types lookup. I'll open a feature request for that.

My interim fix is to resolve the realpath before matching any files. But that will not work for cases where subfolders or individual files are symlinked.

Some possible workarounds on your side until this is fixed:

ajafff commented 6 years ago

@gustofbreak It turns out the quick fix I had in mind only works if node_modules or node_modules/@types is a symlink. It doesn't work if any subdirectory is a symlink. Therefore I will refrain from adding a useless workaround. I opened https://github.com/Microsoft/TypeScript/issues/26684 to request a new API to solve this issue.

Until this is implemented upstream you could use one of the workarounds from my previous posts.

gustofbreak commented 6 years ago

Thanks for the quick investigation!

BTW, using CLI with -e './types/next/**' failed so I didn't thought it would work without prefixing ./.

I tried exclude option in .wotanrc.yaml and it works fine. (I couldn't use typeRoots since it only affects "global declarations".)

I'll left this issue open for future resolution but you can close this if it's preferred.

ajafff commented 6 years ago

using CLI with -e './types/next/**' failed so I didn't thought it would work without prefixing ./.

This is fixed by #388 as well.

I'll left this issue open for future resolution

Agreed. Let's leave it open until this is really fixed.