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

WIP add useFileCompiler setting #616

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
108 changes: 63 additions & 45 deletions lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ module compile {
sortOutput?: boolean;

getCustomTransformers?: GetCustomTransformers;
typescript?: typeof ts;

isolatedModules?: boolean;

Expand All @@ -166,80 +165,99 @@ module compile {
// Unsupported by gulp-typescript
sourceRoot?: string; // Use sourceRoot in gulp-sourcemaps instead
}

export interface GulpTsSettings {
useFileCompiler?: boolean;
typescript?: typeof ts;
}

export type Project = _project.Project;
export type CompileStream = _project.ICompileStream;
export import reporter = _reporter;

export function createProject(tsConfigFileName: string, settings?: Settings): Project;
export function createProject(settings?: Settings): Project;
export function createProject(fileNameOrSettings?: string | Settings, settings?: Settings): Project {
function _createProject({
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normal arguments instead of an object, as you are giving all properties at both calls. So an object does not really add a value here.

tsConfigFileName,
settings,
gulpTsSettings
}: {
tsConfigFileName: string | undefined;
settings: Settings;
gulpTsSettings: GulpTsSettings;
}): Project {
let finalTransformers: FinalTransformers;
let tsConfigFileName: string = undefined;
let tsConfigContent: TsConfig = undefined;
let projectDirectory = process.cwd();
let typescript: typeof ts;
let compilerOptions: ts.CompilerOptions;
let projectReferences: ReadonlyArray<ts.ProjectReference>;
let fileName: string;

let rawConfig: any;

if (fileNameOrSettings !== undefined) {
if (typeof fileNameOrSettings === 'string') {
fileName = fileNameOrSettings;
tsConfigFileName = path.resolve(process.cwd(), fileName);
projectDirectory = path.dirname(tsConfigFileName);
if (settings === undefined) settings = {};
} else {
settings = fileNameOrSettings || {};
}

finalTransformers = getFinalTransformers(settings.getCustomTransformers);
finalTransformers = getFinalTransformers(settings.getCustomTransformers);

typescript = getTypeScript(settings.typescript);
settings = checkAndNormalizeSettings(settings);
typescript = getTypeScript(settings.typescript, gulpTsSettings.typescript);
settings = checkAndNormalizeSettings(settings);

const settingsResult = typescript.convertCompilerOptionsFromJson(settings, projectDirectory);

if (settingsResult.errors) {
reportErrors(settingsResult.errors, typescript);
}
const settingsResult = typescript.convertCompilerOptionsFromJson(settings, projectDirectory);

compilerOptions = settingsResult.options;
if (settingsResult.errors) {
reportErrors(settingsResult.errors, typescript);
}

if (fileName !== undefined) {
let tsConfig = typescript.readConfigFile(tsConfigFileName, typescript.sys.readFile);
if (tsConfig.error) {
console.log(tsConfig.error.messageText);
}
compilerOptions = settingsResult.options;

let parsed: ts.ParsedCommandLine =
typescript.parseJsonConfigFileContent(
tsConfig.config || {},
getTsconfigSystem(typescript),
path.resolve(projectDirectory),
compilerOptions,
tsConfigFileName);
if (tsConfigFileName !== undefined) {
let tsConfig = typescript.readConfigFile(tsConfigFileName, typescript.sys.readFile);
if (tsConfig.error) {
console.log(tsConfig.error.messageText);
}

rawConfig = parsed.raw;
let parsed: ts.ParsedCommandLine =
typescript.parseJsonConfigFileContent(
tsConfig.config || {},
getTsconfigSystem(typescript),
path.resolve(projectDirectory),
compilerOptions,
tsConfigFileName);

tsConfigContent = parsed.raw;
rawConfig = parsed.raw;

if (parsed.errors) {
reportErrors(parsed.errors, typescript, [18003]);
}
tsConfigContent = parsed.raw;

compilerOptions = parsed.options;
projectReferences = parsed.projectReferences;
if (parsed.errors) {
reportErrors(parsed.errors, typescript, [18003]);
}

compilerOptions = parsed.options;
projectReferences = parsed.projectReferences;
}

normalizeCompilerOptions(compilerOptions, typescript);
const project = _project.setupProject(projectDirectory, tsConfigFileName, rawConfig, tsConfigContent, compilerOptions, projectReferences, typescript, finalTransformers);
const project = _project.setupProject(projectDirectory, tsConfigFileName, rawConfig, tsConfigContent, compilerOptions, projectReferences, typescript, finalTransformers, gulpTsSettings.useFileCompiler);

return project;
}

export function createProject(tsConfigFileName: string, settings?: Settings, gulpTsSettings?: GulpTsSettings): Project;
export function createProject(settings?: Settings, gulpTsSettings?: GulpTsSettings): Project;

export function createProject(fileNameOrSettings?: string | Settings, settingsOrGulpTsSettings?: Settings | GulpTsSettings, gulpTsSettingsParam?: GulpTsSettings): Project {
// overload: createProject(tsConfigFileName, settings, gulpTsSettings)
if (typeof fileNameOrSettings === 'string') {
return _createProject({
tsConfigFileName: fileNameOrSettings,
settings: settingsOrGulpTsSettings || {},
gulpTsSettings: gulpTsSettingsParam || {} }
);
}
// overload: createProject(settings, gulpTsSettings)
return _createProject({
tsConfigFileName: undefined,
settings: fileNameOrSettings || {},
gulpTsSettings: settingsOrGulpTsSettings as GulpTsSettings || {} }
);
}

export function filter(...args: any[]) {
utils.deprecate('ts.filter() is deprecated',
'soon you can use tsProject.resolve()',
Expand Down
17 changes: 12 additions & 5 deletions lib/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,24 @@ export interface ProjectInfo {
reporter: Reporter;
}

export function setupProject(projectDirectory: string, configFileName: string, rawConfig: any, config: TsConfig, options: ts.CompilerOptions, projectReferences: ReadonlyArray<ts.ProjectReference>, typescript: typeof ts, finalTransformers: FinalTransformers) {
export function setupProject(projectDirectory: string, configFileName: string, rawConfig: any, config: TsConfig, options: ts.CompilerOptions, projectReferences: ReadonlyArray<ts.ProjectReference>, typescript: typeof ts, finalTransformers: FinalTransformers, useFileCompiler: boolean | undefined) {
const input = new FileCache(typescript, options);
const compiler: ICompiler = options.isolatedModules ? new FileCompiler() : new ProjectCompiler();
let running = false;
if (useFileCompiler && !options.isolatedModules) {
throw Error("useFileCompiler: true can only be used if config.compilerOptions.isolatedModules is also set to true");
}
let compiler: ICompiler;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be indented with tabs


if (options.isolatedModules) {
if (options.isolatedModules && (useFileCompiler === undefined || useFileCompiler === true)) {
compiler = new FileCompiler();
options.newLine = typescript.NewLineKind.LineFeed;
options.sourceMap = false;
options.declaration = false;
options.inlineSourceMap = true;
}
}
else {
compiler = new ProjectCompiler();
}
let running = false;

const project: PartialProject = (reporter) => {
if (running) {
Expand Down
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Almost all options from TypeScript are supported.
- `noEmitOnError` (boolean) - Do not emit outputs if any type checking errors were reported.
- `noEmitHelpers` (boolean) - Do not generate custom helper functions like __extends in compiled output.
- `preserveConstEnums` (boolean) - Do not erase const enum declarations in generated code.
- `isolatedModules` (boolean) - Compiles files seperately and doesn't check types, which causes a big speed increase. You have to use gulp-plumber and TypeScript 1.5+.
- `isolatedModules` (boolean) - By default, this option compiles files seperately and doesn't check types, which causes a big speed increase. You have to use gulp-plumber and TypeScript 1.5+. If you use the `createProject` API (see below) and specify `useFileCompiler: false`, the meaning changes to match that of `tsc`. That is, you *will* get type-checking at the cost of slower compilation. In addition, TypeScript will error on constructs that would prevent safe separate compilation.
- `allowJs` (boolean) - Allow JavaScript files to be compiled.
- `rootDir` - Specifies the root directory of input files. Only use to control the output directory structure with `outDir`.

Expand All @@ -60,7 +60,8 @@ API overview
gulp-typescript can be imported using `const ts = require('gulp-typescript');`. It provides the following functions:

- `ts(options?)` - Returns a gulp stream that compiles TypeScript files using the specified options.
- `ts.createProject(options?)`, `ts.createProject(tsconfig filename, options?)` - Returns a project. The intended usage is to create a project outside of a task with `const tsProject = ts.createProject(..);`. Within a task, `tsProject()` can be used to compile a stream of TypeScript files.
- `ts.createProject(options?)`, `ts.createProject(tsconfig filename?: string, options?: CompilerOptions, gulpTsOptions?: GulpTsOptions)` - Returns a project. The intended usage is to create a project outside of a task with `const tsProject = ts.createProject(..);`. Within a task, `tsProject()` can be used to compile a stream of TypeScript files. The shape of `GulpTsOptions` is `{ useFileCompiler: boolean, typescript: TS }`. `useFileCompiler` defaults to `true` when `isolatedModules` is `true`. Specify `useFileCompiler: false` to use the project compiler even if `isolatedModules` is `true`.
> The important differences are that the project compiler does type checking but the file compiler is faster and more more memory-efficient. Using `isolatedModules` and `useFileCompiler: false` together does extra type-checking that ensures that `useFileCompiler: true` *would* be safe.
- `tsProject.src()` - Returns a stream containing the source files (.ts) from a tsconfig file. It can only be used if you create a project with a `tsconfig.json` file. It is a replacement for `gulp.src(..)`.

Both `ts(..)` and `tsProject()` provide sub-streams that only contain the JavaScript or declaration files. An example is shown later in the readme.
Expand Down
8 changes: 6 additions & 2 deletions release/main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,15 @@ declare module compile {
[name: string]: any;
sourceRoot?: string;
}
interface GulpTsSettings {
useFileCompiler?: boolean;
typescript?: typeof ts;
}
type Project = _project.Project;
type CompileStream = _project.ICompileStream;
export import reporter = _reporter;
function createProject(tsConfigFileName: string, settings?: Settings): Project;
function createProject(settings?: Settings): Project;
function createProject(tsConfigFileName: string, settings?: Settings, gulpTsSettings?: GulpTsSettings): Project;
function createProject(settings?: Settings, gulpTsSettings?: GulpTsSettings): Project;
function filter(...args: any[]): void;
}
export = compile;
78 changes: 42 additions & 36 deletions release/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ function getFinalTransformers(getCustomTransformers) {
}
return null;
}
function getTypeScript(typescript) {
function getTypeScript(settingsTs, gulpTsSettingsTs) {
if (settingsTs && gulpTsSettingsTs && settingsTs !== gulpTsSettingsTs) {
throw Error("settings.typescript and gulpTsSettings.typescript aren't equal. Please specify only one or use the same `typescript` for both.");
}
const typescript = settingsTs || gulpTsSettingsTs;
if (typescript)
return typescript;
try {
Expand Down Expand Up @@ -98,54 +102,56 @@ function reportErrors(errors, typescript, ignore = []) {
}
(function (compile) {
compile.reporter = _reporter;
function createProject(fileNameOrSettings, settings) {
function _createProject({ tsConfigFileName, settings, gulpTsSettings }) {
let finalTransformers;
let tsConfigFileName = undefined;
let tsConfigContent = undefined;
let projectDirectory = process.cwd();
let typescript;
let compilerOptions;
let projectReferences;
let fileName;
let rawConfig;
if (fileNameOrSettings !== undefined) {
if (typeof fileNameOrSettings === 'string') {
fileName = fileNameOrSettings;
tsConfigFileName = path.resolve(process.cwd(), fileName);
projectDirectory = path.dirname(tsConfigFileName);
if (settings === undefined)
settings = {};
}
else {
settings = fileNameOrSettings || {};
}
finalTransformers = getFinalTransformers(settings.getCustomTransformers);
typescript = getTypeScript(settings.typescript);
settings = checkAndNormalizeSettings(settings);
const settingsResult = typescript.convertCompilerOptionsFromJson(settings, projectDirectory);
if (settingsResult.errors) {
reportErrors(settingsResult.errors, typescript);
finalTransformers = getFinalTransformers(settings.getCustomTransformers);
typescript = getTypeScript(settings.typescript, gulpTsSettings.typescript);
settings = checkAndNormalizeSettings(settings);
const settingsResult = typescript.convertCompilerOptionsFromJson(settings, projectDirectory);
if (settingsResult.errors) {
reportErrors(settingsResult.errors, typescript);
}
compilerOptions = settingsResult.options;
if (tsConfigFileName !== undefined) {
let tsConfig = typescript.readConfigFile(tsConfigFileName, typescript.sys.readFile);
if (tsConfig.error) {
console.log(tsConfig.error.messageText);
}
compilerOptions = settingsResult.options;
if (fileName !== undefined) {
let tsConfig = typescript.readConfigFile(tsConfigFileName, typescript.sys.readFile);
if (tsConfig.error) {
console.log(tsConfig.error.messageText);
}
let parsed = typescript.parseJsonConfigFileContent(tsConfig.config || {}, getTsconfigSystem(typescript), path.resolve(projectDirectory), compilerOptions, tsConfigFileName);
rawConfig = parsed.raw;
tsConfigContent = parsed.raw;
if (parsed.errors) {
reportErrors(parsed.errors, typescript, [18003]);
}
compilerOptions = parsed.options;
projectReferences = parsed.projectReferences;
let parsed = typescript.parseJsonConfigFileContent(tsConfig.config || {}, getTsconfigSystem(typescript), path.resolve(projectDirectory), compilerOptions, tsConfigFileName);
rawConfig = parsed.raw;
tsConfigContent = parsed.raw;
if (parsed.errors) {
reportErrors(parsed.errors, typescript, [18003]);
}
compilerOptions = parsed.options;
projectReferences = parsed.projectReferences;
}
normalizeCompilerOptions(compilerOptions, typescript);
const project = _project.setupProject(projectDirectory, tsConfigFileName, rawConfig, tsConfigContent, compilerOptions, projectReferences, typescript, finalTransformers);
const project = _project.setupProject(projectDirectory, tsConfigFileName, rawConfig, tsConfigContent, compilerOptions, projectReferences, typescript, finalTransformers, gulpTsSettings.useFileCompiler);
return project;
}
function createProject(fileNameOrSettings, settingsOrGulpTsSettings, gulpTsSettingsParam) {
// overload: createProject(tsConfigFileName, settings, gulpTsSettings)
if (typeof fileNameOrSettings === 'string') {
return _createProject({
tsConfigFileName: fileNameOrSettings,
settings: settingsOrGulpTsSettings || {},
gulpTsSettings: gulpTsSettingsParam || {}
});
}
// overload: createProject(settings, gulpTsSettings)
return _createProject({
tsConfigFileName: undefined,
settings: fileNameOrSettings || {},
gulpTsSettings: settingsOrGulpTsSettings || {}
});
}
compile.createProject = createProject;
function filter(...args) {
utils.deprecate('ts.filter() is deprecated', 'soon you can use tsProject.resolve()', 'Filters have been removed as of gulp-typescript 3.0.\nSoon tsProject.resolve() will be available as an alternative.\nSee https://github.com/ivogabe/gulp-typescript/issues/190.');
Expand Down
2 changes: 1 addition & 1 deletion release/project.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface ProjectInfo {
directory: string;
reporter: Reporter;
}
export declare function setupProject(projectDirectory: string, configFileName: string, rawConfig: any, config: TsConfig, options: ts.CompilerOptions, projectReferences: ReadonlyArray<ts.ProjectReference>, typescript: typeof ts, finalTransformers: FinalTransformers): Project;
export declare function setupProject(projectDirectory: string, configFileName: string, rawConfig: any, config: TsConfig, options: ts.CompilerOptions, projectReferences: ReadonlyArray<ts.ProjectReference>, typescript: typeof ts, finalTransformers: FinalTransformers, useFileCompiler: boolean | undefined): Project;
export interface ICompileStream extends NodeJS.ReadWriteStream {
js: stream.Readable;
dts: stream.Readable;
Expand Down
15 changes: 11 additions & 4 deletions release/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,23 @@ const reporter_1 = require("./reporter");
const input_1 = require("./input");
const output_1 = require("./output");
const compiler_1 = require("./compiler");
function setupProject(projectDirectory, configFileName, rawConfig, config, options, projectReferences, typescript, finalTransformers) {
function setupProject(projectDirectory, configFileName, rawConfig, config, options, projectReferences, typescript, finalTransformers, useFileCompiler) {
const input = new input_1.FileCache(typescript, options);
const compiler = options.isolatedModules ? new compiler_1.FileCompiler() : new compiler_1.ProjectCompiler();
let running = false;
if (options.isolatedModules) {
if (useFileCompiler && !options.isolatedModules) {
throw Error("useFileCompiler: true can only be used if config.compilerOptions.isolatedModules is also set to true");
}
let compiler;
if (options.isolatedModules && (useFileCompiler === undefined || useFileCompiler === true)) {
compiler = new compiler_1.FileCompiler();
options.newLine = typescript.NewLineKind.LineFeed;
options.sourceMap = false;
options.declaration = false;
options.inlineSourceMap = true;
}
else {
compiler = new compiler_1.ProjectCompiler();
}
let running = false;
const project = (reporter) => {
if (running) {
throw new Error('gulp-typescript: A project cannot be used in two compilations at the same time. Create multiple projects with createProject instead.');
Expand Down
12 changes: 12 additions & 0 deletions test/baselines/useFileCompiler/2.3/errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
TypeScript error: test/useFileCompiler/excluded-dir/test.ts(1,1): error TS2304: Cannot find name 'notCompiled'.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please ignore these tests, they are a little borked right now

TypeScript error: test/useFileCompiler/excluded-file.ts(1,1): error TS2304: Cannot find name 'notCompiled'.
{
"transpileErrors": 0,
"optionsErrors": 0,
"syntaxErrors": 0,
"globalErrors": 0,
"semanticErrors": 2,
"declarationErrors": 0,
"emitErrors": 0,
"emitSkipped": false
}
3 changes: 3 additions & 0 deletions test/baselines/useFileCompiler/2.3/js/excluded-dir/test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions test/baselines/useFileCompiler/2.3/js/excluded-file.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/baselines/useFileCompiler/2.3/js/excluded-file.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading