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

Refactor node factory API, use node factory in parser #35282

Merged
merged 20 commits into from Jun 16, 2020
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter
Filter file types
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -43,7 +43,7 @@
},
"sourceMaps": true,
"smartStep": true,
"preLaunchTask": "tests",
"preLaunchTask": "gulp: tests",
"console": "integratedTerminal",
"outFiles": [
"${workspaceRoot}/built/local/run.js"
@@ -4,31 +4,42 @@
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"identifier": "local",
"type": "gulp",
"label": "gulp: local",
"command": "gulp",
"args": ["local"],
"group": { "kind": "build", "isDefault": true },
"problemMatcher": ["$gulp-tsc"]
"task": "local",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$tsc"
]
},
{
"type": "shell",
"identifier": "tsc",
"type": "gulp",
"label": "gulp: tsc",
"command": "gulp",
"args": ["tsc"],
"task": "tsc",
"group": "build",
"problemMatcher": ["$gulp-tsc"]
"problemMatcher": [
"$tsc"
]
},
{
"type": "shell",
"identifier": "tests",
"type": "gulp",
"label": "gulp: tests",
"command": "gulp",
"args": ["tests"],
"task": "tests",
"group": "build",
"problemMatcher": ["$gulp-tsc"]
"problemMatcher": [
"$tsc"
]
},
{
"type": "gulp",
"task": "services",
"label": "gulp: services",
"problemMatcher": [
"$tsc"
],
}
]
}

Large diffs are not rendered by default.

@@ -0,0 +1,12 @@
{
"extends": "../tsconfig-base",
"compilerOptions": {
"outFile": "../../built/local/compat.js"
},
"references": [
{ "path": "../compiler" }
],
"files": [
"deprecations.ts"
]
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -1516,6 +1516,20 @@ namespace ts {
};
}

/** A version of `memoize` that supports a single primitive argument */
export function memoizeOne<A extends string | number | boolean | undefined, T>(callback: (arg: A) => T): (arg: A) => T {
const map = createMap<T>();
return (arg: A) => {
const key = `${typeof arg}:${arg}`;
let value = map.get(key);
if (value === undefined && !map.has(key)) {
value = callback(arg);
map.set(key, value);
}
return value!;
};
}

/**
* High-order function, composes functions. Note that functions are composed inside-out;
* for example, `compose(a, b)` is the equivalent of `x => b(a(x))`.
@@ -79,6 +79,7 @@ namespace ts {
/** Array that is only intended to be pushed to, never read. */
export interface Push<T> {
push(...values: T[]): void;
/* @internal*/ readonly length: number;
}

/* @internal */
@@ -1,12 +1,72 @@
/* @internal */
namespace ts {
export enum LogLevel {
Off,
Error,
Warning,
Info,
Verbose
}

export interface LoggingHost {
log(level: LogLevel, s: string): void;
}

export interface DeprecationOptions {
message?: string;
error?: boolean;
since?: Version | string;
warnAfter?: Version | string;
errorAfter?: Version | string;
typeScriptVersion?: Version | string;
}

export namespace Debug {
let currentAssertionLevel = AssertionLevel.None;
let typeScriptVersion: Version | undefined;

// eslint-disable-next-line prefer-const
/* eslint-disable prefer-const */
let currentAssertionLevel = AssertionLevel.None;
export let currentLogLevel = LogLevel.Warning;
export let isDebugging = false;
export let loggingHost: LoggingHost | undefined;
/* eslint-enable prefer-const */

type AssertionKeys = MatchingKeys<typeof Debug, AnyFunction>;
export function getTypeScriptVersion() {
return typeScriptVersion ?? (typeScriptVersion = new Version(version));
}

export function shouldLog(level: LogLevel): boolean {
return currentLogLevel <= level;
}

function logMessage(level: LogLevel, s: string): void {
if (loggingHost && shouldLog(level)) {
loggingHost.log(level, s);
}
}

export function log(s: string): void {
logMessage(LogLevel.Info, s);
}

export namespace log {
export function error(s: string): void {
logMessage(LogLevel.Error, s);
}

export function warn(s: string): void {
logMessage(LogLevel.Warning, s);
}

export function log(s: string): void {
logMessage(LogLevel.Info, s);
}

export function trace(s: string): void {
logMessage(LogLevel.Verbose, s);
}
}

const assertionCache: Partial<Record<AssertionKeys, { level: AssertionLevel, assertion: AnyFunction }>> = {};

@@ -385,7 +445,7 @@ namespace ts {
if (nodeIsSynthesized(this)) return "";
const parseNode = getParseTreeNode(this);
const sourceFile = parseNode && getSourceFileOfNode(parseNode);
return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : "";
return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode!, includeTrivia) : "";
}
}
});
@@ -410,5 +470,56 @@ namespace ts {
isDebugInfoEnabled = true;
}

function formatDeprecationMessage(name: string, error: boolean | undefined, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
let deprecationMessage = error ? "DeprecationError: " : "DeprecationWarning: ";
deprecationMessage += `'${name}' `;
deprecationMessage += since ? `has been deprecated since v${since}` : "is deprecated";
deprecationMessage += error ? " and can no longer be used." : errorAfter ? ` and will no longer be usable after v${errorAfter}.` : ".";
deprecationMessage += message ? ` ${formatStringFromArgs(message, [name], 0)}` : "";
return deprecationMessage;
}

function createErrorDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
const deprecationMessage = formatDeprecationMessage(name, /*error*/ true, errorAfter, since, message);
return () => {
throw new TypeError(deprecationMessage);
};
}

function createWarningDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
let hasWrittenDeprecation = false;
return () => {
if (!hasWrittenDeprecation) {
log.warn(formatDeprecationMessage(name, /*error*/ false, errorAfter, since, message));
hasWrittenDeprecation = true;
}
};
}

function createDeprecation(name: string, options: DeprecationOptions & { error: true }): () => never;
function createDeprecation(name: string, options?: DeprecationOptions): () => void;
function createDeprecation(name: string, options: DeprecationOptions = {}) {
const version = typeof options.typeScriptVersion === "string" ? new Version(options.typeScriptVersion) : options.typeScriptVersion ?? getTypeScriptVersion();
const errorAfter = typeof options.errorAfter === "string" ? new Version(options.errorAfter) : options.errorAfter;
const warnAfter = typeof options.warnAfter === "string" ? new Version(options.warnAfter) : options.warnAfter;
const since = typeof options.since === "string" ? new Version(options.since) : options.since ?? warnAfter;
const error = options.error || errorAfter && version.compareTo(errorAfter) <= 0;
const warn = !warnAfter || version.compareTo(warnAfter) >= 0;
return error ? createErrorDeprecation(name, errorAfter, since, options.message) :
warn ? createWarningDeprecation(name, errorAfter, since, options.message) :
noop;
}

function wrapFunction<F extends (...args: any[]) => any>(deprecation: () => void, func: F): F {
return function (this: unknown) {
deprecation();
return func.apply(this, arguments);
} as F;
}

export function deprecate<F extends (...args: any[]) => any>(func: F, options?: DeprecationOptions): F {
const deprecation = createDeprecation(getFunctionName(func), options);
return wrapFunction(deprecation, func);
}
}
}
@@ -28,7 +28,7 @@ namespace ts {
if (outFile(options)) {
const prepends = host.getPrependNodes();
if (sourceFiles.length || prepends.length) {
const bundle = createBundle(sourceFiles, prepends);
const bundle = factory.createBundle(sourceFiles, prepends);
const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle);
if (result) {
return result;
@@ -356,7 +356,7 @@ namespace ts {
return;
}
// Transform the source files
const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false);
const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false);

const printerOptions: PrinterOptions = {
removeComments: compilerOptions.removeComments,
@@ -404,13 +404,13 @@ namespace ts {
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson);
// Setup and perform the transformation to retrieve declarations from the input files
const inputListOrBundle = outFile(compilerOptions) ? [createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit;
const inputListOrBundle = outFile(compilerOptions) ? [factory.createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit;
if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) {
// Checker wont collect the linked aliases since thats only done when declaration is enabled.
// Do that here when emitting only dts files
filesForEmit.forEach(collectLinkedAliases);
}
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false);
const declarationTransform = transformNodes(resolver, host, factory, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false);
if (length(declarationTransform.diagnostics)) {
for (const diagnostic of declarationTransform.diagnostics!) {
emitterDiagnostics.add(diagnostic);
@@ -680,30 +680,30 @@ namespace ts {
}

function createSourceFilesFromBundleBuildInfo(bundle: BundleBuildInfo, buildInfoDirectory: string, host: EmitUsingBuildInfoHost): readonly SourceFile[] {
const sourceFiles = bundle.sourceFiles.map(fileName => {
const sourceFile = createNode(SyntaxKind.SourceFile, 0, 0) as SourceFile;
const jsBundle = Debug.checkDefined(bundle.js);
const prologueMap = jsBundle.sources?.prologues && arrayToMap(jsBundle.sources.prologues, prologueInfo => "" + prologueInfo.file);
return bundle.sourceFiles.map((fileName, index) => {
const prologueInfo = prologueMap?.get("" + index);
const statements = prologueInfo?.directives.map(directive => {
const literal = setTextRange(factory.createStringLiteral(directive.expression.text), directive.expression);
const statement = setTextRange(factory.createExpressionStatement(literal), directive);
setParent(literal, statement);
return statement;
});
const eofToken = factory.createToken(SyntaxKind.EndOfFileToken);
const sourceFile = factory.createSourceFile(statements ?? [], eofToken, NodeFlags.None);
sourceFile.fileName = getRelativePathFromDirectory(
host.getCurrentDirectory(),
getNormalizedAbsolutePath(fileName, buildInfoDirectory),
!host.useCaseSensitiveFileNames()
);
sourceFile.text = "";
sourceFile.statements = createNodeArray();
sourceFile.text = prologueInfo?.text ?? "";
setTextRangePosWidth(sourceFile, 0, prologueInfo?.text.length ?? 0);
setEachParent(sourceFile.statements, sourceFile);
setTextRangePosWidth(eofToken, sourceFile.end, 0);
setParent(eofToken, sourceFile);
return sourceFile;
});
const jsBundle = Debug.checkDefined(bundle.js);
forEach(jsBundle.sources && jsBundle.sources.prologues, prologueInfo => {
const sourceFile = sourceFiles[prologueInfo.file];
sourceFile.text = prologueInfo.text;
sourceFile.end = prologueInfo.text.length;
sourceFile.statements = createNodeArray(prologueInfo.directives.map(directive => {
const statement = createNode(SyntaxKind.ExpressionStatement, directive.pos, directive.end) as PrologueDirective;
statement.expression = createNode(SyntaxKind.StringLiteral, directive.expression.pos, directive.expression.end) as StringLiteral;
statement.expression.text = directive.expression.text;
return statement;
}));
});
return sourceFiles;
}

/*@internal*/
@@ -2292,7 +2292,7 @@ namespace ts {

function emitPropertyAccessExpression(node: PropertyAccessExpression) {
const expression = cast(emitExpression(node.expression), isExpression);
const token = node.questionDotToken || createNode(SyntaxKind.DotToken, node.expression.end, node.name.pos) as DotToken;
const token = node.questionDotToken || setTextRangePosEnd(factory.createToken(SyntaxKind.DotToken) as DotToken, node.expression.end, node.name.pos);
const linesBeforeDot = getLinesBetweenNodes(node, node.expression, token);
const linesAfterDot = getLinesBetweenNodes(node, token, node.name);

@@ -3559,15 +3559,15 @@ namespace ts {
}

function emitJSDocTypeLiteral(lit: JSDocTypeLiteral) {
emitList(lit, createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment);
emitList(lit, factory.createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment);
}

function emitJSDocSignature(sig: JSDocSignature) {
if (sig.typeParameters) {
emitList(sig, createNodeArray(sig.typeParameters), ListFormat.JSDocComment);
emitList(sig, factory.createNodeArray(sig.typeParameters), ListFormat.JSDocComment);
}
if (sig.parameters) {
emitList(sig, createNodeArray(sig.parameters), ListFormat.JSDocComment);
emitList(sig, factory.createNodeArray(sig.parameters), ListFormat.JSDocComment);
}
if (sig.type) {
writeLine();
ProTip! Use n and p to navigate between commits in a pull request.