panuhorsmalahti / gulp-tslint

TypeScript linter plugin for Gulp
MIT License
118 stars 44 forks source link

Error when running rules that require type info #105

Closed ChrisMBarr closed 1 year ago

ChrisMBarr commented 7 years ago

typescript version: 2.1.5 gulp-tslint version: 7.0.1 tslint version: 4.4.1 Operating system: Windows 10


Whenever I enable any tslint rule that require type info, I get the error shown below. Example: "restrict-plus-operands": true

Am I setting this up correctly? Rules that don not require type info seem to work just fine.

Gulp configuration

const gulp        = require("gulp");
const gulpTslint  = require("gulp-tslint");
const ts          = require("gulp-typescript");
const tslint      = require("tslint");

const tsProject = ts.createProject("./tsconfig.json");

gulp.task("lint", () => {
    const tslintProgram = tslint.Linter.createProgram("./tsconfig.json", ".");

    const tsResult = tsProject.src()
        .pipe(gulpTslint({
            formatter: "stylish",
            program: tslintProgram
        }))
        .pipe(gulpTslint.report({
            emitError: false,
            reportLimit: 50
        }))
        .pipe(tsProject());

    return tsResult.js.pipe(gulp.dest("./"));
});

Error console output:

[07:42:23] Using gulpfile C:\<my-project>\gulpfile.js
[07:42:23] Starting 'lint'...
stream.js:74
      throw er; // Unhandled stream error in pipe.
      ^

TypeError: Cannot read property 'name' of undefined
    at getSignatureFromDeclaration (C:\<my-project>\node_modules\typescript\lib\typescript.js:28873:47)
    at getThisTypeOfDeclaration (C:\<my-project>\node_modules\typescript\lib\typescript.js:27447:43)
    at checkThisExpression (C:\<my-project>\node_modules\typescript\lib\typescript.js:34029:32)
    at checkExpressionWorker (C:\<my-project>\node_modules\typescript\lib\typescript.js:38187:28)
    at checkExpression (C:\<my-project>\node_modules\typescript\lib\typescript.js:38165:42)
    at checkNonNullExpression (C:\<my-project>\node_modules\typescript\lib\typescript.js:35540:24)
    at checkPropertyAccessExpressionOrQualifiedName (C:\<my-project>\node_modules\typescript\lib\typescript.js:35587:24)
    at checkPropertyAccessExpression (C:\<my-project>\node_modules\typescript\lib\typescript.js:35554:20)
    at checkExpressionWorker (C:\<my-project>\node_modules\typescript\lib\typescript.js:38208:28)
    at checkExpression (C:\<my-project>\node_modules\typescript\lib\typescript.js:38165:42)
panuhorsmalahti commented 7 years ago

Try without const tsProject = ts.createProject("./tsconfig.json"); and .pipe(tsProject());

ChrisMBarr commented 7 years ago

I've tried this this way

const gulp        = require("gulp");
const gulpTslint  = require("gulp-tslint");
const ts          = require("gulp-typescript");
const tslint      = require("tslint");

gulp.task("lint", () => {
    const tslintProgram = tsLint.Linter.createProgram("./tsconfig.json", ".");

    const tsResult = gulp.src(["app/**/*.ts"])
        .pipe(gulpTsLint({
            formatter: 'stylish',
            program: tslintProgram
        }))
        .pipe(gulpTsLint.report({
            emitError: true,
            summarizeFailureOutput: false
        }));

    return tsResult.pipe(gulp.dest("./"));
});

and this way

const gulp        = require("gulp");
const gulpTslint  = require("gulp-tslint");
const ts          = require("gulp-typescript");
const tslint      = require("tslint");

gulp.task("lint", () => {
    const tslintProgram = tsLint.Linter.createProgram("./tsconfig.json", ".");

    return gulp.src(TS_FILES)
        .pipe(gulpTsLint({
            formatter: 'stylish',
            program: tslintProgram
        }))
        .pipe(gulpTsLint.report({
            emitError: true,
            summarizeFailureOutput: false
        }));
});

and they both throw this error

stream.js:74
      throw er; // Unhandled stream error in pipe.
      ^
Error: 
Invalid source file: state.model.ts. Ensure that the files supplied to lint have a .ts, .tsx, .js or .jsx extension.

    at Linter.getSourceFile (C:\<my-project>\node_modules\tslint\lib\linter.js:187:19)
    at Linter.getEnabledRules (C:\<my-project>\node_modules\tslint\lib\linter.js:156:31)
    at Linter.lint (C:\<my-project>\node_modules\tslint\lib\linter.js:83:33)
    at C:\<my-project>\node_modules\gulp-tslint\index.js:102:16
    at wrappedMapper (C:\<my-project>\node_modules\map-stream\index.js:84:19)
    at Stream.stream.write (C:\<my-project>\node_modules\map-stream\index.js:96:21)
    at write (C:\<my-project>\node_modules\vinyl-fs\node_modules\readable-stream\lib\_stream_readable.js:623:24)
    at flow (C:\<my-project>\node_modules\vinyl-fs\node_modules\readable-stream\lib\_stream_readable.js:632:7)
    at DestroyableTransform.pipeOnReadable (C:\<my-project>\node_modules\vinyl-fs\node_modules\readable-stream\lib\_stream_readable.js:664:5)
    at emitNone (events.js:67:13)
Process terminated with code 1.

Note that the file listed, state.model.ts is the alphabetically first file that would be encounter with the glob pattern provided.

At this point I've tried everything I know of to get this working and I've even followed the documentation. I'm not sure what I'm missing here, but I've attempted this on 2 separate projects not (each on a totally different computer).

I have a feeling these issues are related, but from my perspective I can't tell if this is an issue with typescript itself, tslint, or with this project.

https://github.com/palantir/tslint/issues/2133 https://github.com/palantir/tslint/issues/1909 https://github.com/panuhorsmalahti/gulp-tslint/issues/77

panuhorsmalahti commented 7 years ago

Could you provide the source code that you're trying to lint?

m-sureshraj commented 7 years ago

Yep, I'am also having the same issue.

stream.js:74
      throw er; // Unhandled stream error in pipe.
      ^

Error:
Invalid source file: main.ts. Ensure that the files supplied to lint have a .ts, .tsx, .js or .jsx extension.
ChrisMBarr commented 7 years ago

Sure thing!

I made this as simple of an example as possible. Just run npm install. The gulpfile.js has 4 gulp tasks for linting. The 3 variations I provided above that all fail, plus one without typechecking that works.

in the tslint.json file I have one type-checked rule that is disabled. If you can get type checking to work in a task, enable this rule and there's a line of code in example.ts that should throw a violation for it.

Download: ⬇️📁 test.zip

Here's when I get when I run a task with type checking, and then a task without type checking

image

ramishka commented 7 years ago

I'm having the same issue. Tried without const tsProject = ts.createProject("./tsconfig.json"); and .pipe(tsProject()); and several other combinations and still the same result.

ChrisMBarr commented 7 years ago

Has any progress been made with this? It's been about a month since I opened this and I am still unable to use any type-checked linting rules.

deryost commented 7 years ago

Same bug here !

lddubeau commented 7 years ago

The problem is that how to activate type checking through the programmatic API is mostly undocumented. The README gives an example which suggests that the only thing needed is a program but that's not the case at all. TypeScript's getPreEmitDiagnostics must also be called with the program, because this is what produces the type information that the rules later use.

Like others who commented here I've tried everything and got nowhere fast until I added ts.getPreEmitDiagnostics(program); to my Gulp task before starting gulp-tslint, and then I started getting errors generated by the rules that need type checking.

ChrisMBarr commented 7 years ago

@lddubeau !!!!!!!!! That was the key! Why isn't this documented anywhere in this project?

Here's my now working gulp task that can lint type-checked rules!

const gulp        = require("gulp");
const gulpTslint  = require("gulp-tslint");
const ts          = require("typescript");
const tslint      = require("tslint");

gulp.task("lint", () => {
    const tslintProgram = tslint.Linter.createProgram("./tsconfig.json", ".");
    ts.getPreEmitDiagnostics(tslintProgram);

    return gulp.src(TS_FILES)
        .pipe(gulpTsLint({
            formatter: 'stylish',
            program: tslintProgram
        }))
        .pipe(gulpTsLint.report({
            emitError: true,
            summarizeFailureOutput: false
        }));
});

IMO, this configuration should be baked in to the gulp-tslint project. since typescript and tslint are dependencies anyway, this could just happen internally if it was passed the info needed to create the program.

Here's my ideal setup for how I think this should work

const gulp        = require("gulp");
const gulpTslint  = require("gulp-tslint");

gulp.task("lint", () => {
    return gulp.src(TS_FILES)
        .pipe(gulpTsLint({
            formatter: 'stylish',
            programConfig: "./tsconfig.json", //when this is specified, enable type-checked rules
            programLocation: "."  //this should be the default value
        }))
        .pipe(gulpTsLint.report({
            emitError: true,
            summarizeFailureOutput: false
        }));
});
lddubeau commented 7 years ago

@chrismbarr Thanks for the full example. I thought about posting my own but my code is very idiosyncratic and it would have been a pain to clean it up for general consumption. (And probably error-prone too.)

I suspect a complete solution will have to inspect the results of ts.getPreEmitDiagnostics(tslintProgram); and abort on error just like tslint itself does when it is run from the cli.

Martinspire commented 7 years ago

The solution from @chrismbarr doesn't work on my end. It still gives me an error:


stream.js:74
      throw er; // Unhandled stream error in pipe.
      ^

Error:
Invalid source file: C:\....somefile.ts. Ensure that the files supplied to lint have a .ts, .tsx, .js or .jsx extension.```
mogusbi commented 7 years ago

Having the same issue here

Invalid source file: main.ts. Ensure that the files supplied to lint have a .ts, .tsx, .js or .jsx extension.

negberts commented 7 years ago

I had the same error until I changed the path of the tsconfig.json.

It's now relative to the task file instead of the gulpfile.js. (Gulpfile.js and tsconfig.json are in root, gulp task is in tools/tasks/project so in task it's: const tslintProgram = tslint.Linter.createProgram('../../../tsconfig.json', '.'))

EugeneSnihovsky commented 7 years ago

@negberts I'm not sure, but maybe you have wrong tsconfig.json and '../../../tsconfig.json' is wrong path to it (and lint loaded some default tsconfig settings). I checked it on myself with wrong path to tsconfig

const program = tslint.Linter.createProgram('dsasdahykaas.json', '.');

In my case error

Invalid source file: /Volumes/WORKSPACE/projects/_components/ng2-http-wrapper-service/lib/error-handler.spec.ts. Ensure that the files supplied to lint have a .ts, .tsx, .js or .jsx extension.

Was linked to "files" section of tsconfig.json. When I removed it everything started to work

Martinspire commented 7 years ago

@EugeneSnihovsky how does that even conflict with our config file?

Also with an invalid config file i still get the same error (not your last one) and it lists a perfectly fine ts file

dominique-mueller commented 7 years ago

Had the same error with the Invalid source file - fixed it by setting the base property of the gulp.src options. My full working configuration:

const tslintProgram = tslint.Linter.createProgram( 'tsconfig.json' );
typescript.getPreEmitDiagnostics( tslintProgram );

return gulp
  .src( 'src/**/*.ts', {
    base: '.' // This is key!!
  } )
  .pipe( gulpTslint( {
    formatter: 'stylish',
    program: tslintProgram
  } ) )
  .pipe( gulpTslint.report( {
    emitError: true,
    summarizeFailureOutput: true
  } ) );

Also see https://github.com/panuhorsmalahti/gulp-tslint/issues/71.

Martinspire commented 7 years ago

@dominique-mueller tried that, but no sigar.

bolatovumar commented 7 years ago

Anyone else having this issue?

I'm trying to upgrade from TSLint 4.5.1 to 5.2.0 and I start getting the error below as soon as I add

const program = tslint.Linter.createProgram("./tsconfig.json");

Here is the error is it's full glory:

capture

Martinspire commented 7 years ago

@bolatovumar I think almost everybody still has that issue. I haven't found a fix yet so i'm still sticking with the previous version

Martinspire commented 7 years ago

Any update on this? I can't update to the latest version until this gets fixed somehow.

bolatovumar commented 7 years ago

Hey @Martinspire, I was able to get things working. I'm using TS 2.3.4, TSLint 5.4.3 and gulp-tslint 8.1.1 and I don't get this error any more.

KurtPreston commented 7 years ago

We were encountering an identical problem. Eventually, we realized that gulp.src was requiring files that were excluded by the tsconfig.json file. When we changed our gulp.src declaration to exclude these files, the error went away.

m-sureshraj commented 6 years ago

Hi All,

If I try to lint a file which is not covered by the tsconfig.json include property glob pattern then this same error occurred repeatedly for me also. By listing all the .ts files which i want to lint in tsconfig.json file solve the issue for me. My working configuration files:

tsconfig.json

"include": [
  "app/**/*.ts",
  "test/**/*.ts"
]

gulp task file

var gulp = require('gulp');
var gulpTsLint = require('gulp-tslint');
var tsLint = require('tslint');

var tsSource = ['app/**/*.ts', 'test/**/*.ts'];

gulp.task('tslint', function() {
    var program = tsLint.Linter.createProgram('tsconfig.json');

    gulp.src(tsSource)
        .pipe(gulpTsLint({
            formatter: "verbose",
            program: program,
            tslint: tsLint
        }))
        .pipe(gulpTsLint.report({
            emitError: true,
            summarizeFailureOutput: true
        }));
});

Credits: https://github.com/panuhorsmalahti/gulp-tslint/issues/121 @ishitatsuyuki

Martinspire commented 6 years ago

@m-sureshraj if you want you can inject the tsconfig JSON into your gulpfile so you only need to modify it at one location