Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 43 additions & 21 deletions packages/typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { createFilter } from '@rollup/pluginutils';

import type { Plugin, SourceDescription } from 'rollup';
import type { Plugin, PluginContext, SourceDescription } from 'rollup';
import type { Watch } from 'typescript';

import type { RollupTypescriptOptions } from '../types';
Expand Down Expand Up @@ -37,6 +37,31 @@
tslib,
typescript: ts
} = getPluginOptions(options);
const createProgram = (context: PluginContext) =>
createWatchProgram(ts, context, {
formatHost,
resolveModule,
parsedOptions,
writeFile(fileName, data, _writeByteOrderMark, _onError, sourceFiles) {
if (sourceFiles) {
for (const sourceFile of sourceFiles) {
if (!parsedOptions.fileNames.includes(sourceFile.fileName)) {
parsedOptions.fileNames.push(sourceFile.fileName);
}
}
}

if (parsedOptions.options.composite || parsedOptions.options.incremental) {
tsCache.cacheCode(fileName, data);
}
emittedFiles.set(fileName, data);
},
status(diagnostic) {
watchProgramHelper.handleStatus(diagnostic);
},
transformers
});

const tsCache = new TSCache(cacheDir);
const emittedFiles = new Map<string, string>();
const watchProgramHelper = new WatchProgramHelper();
Expand All @@ -56,6 +81,14 @@
name: 'typescript',

buildStart(rollupOptions) {
if (typeof rollupOptions.input === 'string') {
rollupOptions.input = [rollupOptions.input];

Check warning on line 85 in packages/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / Node v20

Assignment to property of function parameter 'rollupOptions'

Check warning on line 85 in packages/typescript/src/index.ts

View workflow job for this annotation

GitHub Actions / Node v18

Assignment to property of function parameter 'rollupOptions'
}

if (Array.isArray(rollupOptions.input)) {
parsedOptions.fileNames = rollupOptions.input.map((fileName) => path.resolve(fileName));
}

emitParsedOptionsErrors(ts, this, parsedOptions);

preflight({
Expand All @@ -74,21 +107,7 @@
program = null;
}
if (!program) {
program = createWatchProgram(ts, this, {
formatHost,
resolveModule,
parsedOptions,
writeFile(fileName, data) {
if (parsedOptions.options.composite || parsedOptions.options.incremental) {
tsCache.cacheCode(fileName, data);
}
emittedFiles.set(fileName, data);
},
status(diagnostic) {
watchProgramHelper.handleStatus(diagnostic);
},
transformers
});
program = createProgram(this);
}
},

Expand Down Expand Up @@ -139,7 +158,6 @@

if (resolved) {
if (/\.d\.[cm]?ts/.test(resolved.extension)) return null;
if (!filter(resolved.resolvedFileName)) return null;
return path.normalize(resolved.resolvedFileName);
}

Expand All @@ -149,16 +167,20 @@
async load(id) {
if (!filter(id)) return null;

this.addWatchFile(id);
const resolvedId = path.resolve(id);

this.addWatchFile(resolvedId);
await watchProgramHelper.wait();

const fileName = normalizePath(id);
const fileName = normalizePath(resolvedId);
if (!parsedOptions.fileNames.includes(fileName)) {
// Discovered new file that was not known when originally parsing the TypeScript config
parsedOptions.fileNames.push(fileName);
parsedOptions.fileNames.push(path.resolve(fileName));

createProgram(this).close();
}

const output = findTypescriptOutput(ts, parsedOptions, id, emittedFiles, tsCache);
const output = findTypescriptOutput(ts, parsedOptions, resolvedId, emittedFiles, tsCache);

return output.code != null ? (output as SourceDescription) : null;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line
foo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {foo} from "./valid";

console.log(foo);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const foo = 5;
18 changes: 17 additions & 1 deletion packages/typescript/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,8 @@ test.serial('does it support tsconfig.rootDir for filtering', async (t) => {
t.is(files.length, 1);
});

test.serial('does it fail for filtering with incorrect rootDir in nested projects', async (t) => {
// todo: why would want to deliberately forbid resolution from outside of CWD? What problem does it solve to add such a constraint?
test.skip('does it fail for filtering with incorrect rootDir in nested projects', async (t) => {
process.chdir('fixtures/root-dir/packages/test-2');
const error = await t.throwsAsync(
rollup({
Expand Down Expand Up @@ -1420,3 +1421,18 @@ test.serial('compiled external library', async (t) => {
});
t.pass();
});

test.serial(
'do not consider files that are not part of the entry point dependency graph',
async (t) => {
process.chdir('fixtures/with-invalid-sources-inside-cwd');
const input = 'main.ts';

const build = await rollup({
input,
plugins: [typescript()]
});

t.deepEqual(build.watchFiles, [path.resolve('main.ts'), path.resolve('valid.ts')]);
}
);
17 changes: 10 additions & 7 deletions packages/typescript/test/tslib.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { platform } from 'os';
import { resolve } from 'path';

import test from 'ava';
import type { RollupError } from 'rollup';
Expand Down Expand Up @@ -62,13 +63,15 @@ test.serial('fails on bad tslib path', async (t) => {
return;
}

if (error.watchFiles) {
let [filePath] = error.watchFiles;
filePath = filePath.substring(filePath.indexOf('packages'));
error.watchFiles[0] = filePath;
}

t.snapshot(error);
t.deepEqual(
error.message,
`Could not load fixtures/joker/tslib.js (imported by fixtures/overriding-tslib/main.ts): ENOENT: no such file or directory, open 'fixtures/joker/tslib.js'`
);
t.deepEqual(error.watchFiles, [
resolve('fixtures/overriding-tslib/main.ts'),
'fixtures/joker/tslib.js'
]);
t.deepEqual(error.code, 'ENOENT');
});

test.serial('fails without tslib installed', async (t) => {
Expand Down
Loading