Merge branch 'small_ts' of https://github.com/orta/TypeScript into small_ts

This commit is contained in:
Orta Therox 2019-09-30 08:41:56 -04:00
commit 4c4a683d03
489 changed files with 24902 additions and 3734 deletions

2
.gitignore vendored
View File

@ -94,4 +94,4 @@ tests/cases/user/webpack/webpack
tests/cases/user/puppeteer/puppeteer
tests/cases/user/axios-src/axios-src
tests/cases/user/prettier/prettier
tmp
.eslintcache

View File

@ -341,6 +341,8 @@ const eslint = (folder) => async () => {
const args = [
"node_modules/eslint/bin/eslint",
"--cache",
"--cache-location", `${folder}/.eslintcache`,
"--format", "autolinkable-stylish",
"--rulesdir", "scripts/eslint/built/rules",
"--ext", ".ts",

View File

@ -13,11 +13,26 @@ namespace ts {
referenced: boolean;
}
export function getModuleInstanceState(node: ModuleDeclaration): ModuleInstanceState {
return node.body ? getModuleInstanceStateWorker(node.body) : ModuleInstanceState.Instantiated;
export function getModuleInstanceState(node: ModuleDeclaration, visited?: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
if (node.body && !node.body.parent) {
// getModuleInstanceStateForAliasTarget needs to walk up the parent chain, so parent pointers must be set on this tree already
setParentPointers(node, node.body);
}
return node.body ? getModuleInstanceStateCached(node.body, visited) : ModuleInstanceState.Instantiated;
}
function getModuleInstanceStateWorker(node: Node): ModuleInstanceState {
function getModuleInstanceStateCached(node: Node, visited = createMap<ModuleInstanceState | undefined>()) {
const nodeId = "" + getNodeId(node);
if (visited.has(nodeId)) {
return visited.get(nodeId) || ModuleInstanceState.NonInstantiated;
}
visited.set(nodeId, undefined);
const result = getModuleInstanceStateWorker(node, visited);
visited.set(nodeId, result);
return result;
}
function getModuleInstanceStateWorker(node: Node, visited: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
// A module is uninstantiated if it contains only
switch (node.kind) {
// 1. interface declarations, type alias declarations
@ -37,11 +52,27 @@ namespace ts {
return ModuleInstanceState.NonInstantiated;
}
break;
// 4. other uninstantiated module declarations.
// 4. Export alias declarations pointing at only uninstantiated modules or things uninstantiated modules contain
case SyntaxKind.ExportDeclaration:
if (!(node as ExportDeclaration).moduleSpecifier && !!(node as ExportDeclaration).exportClause) {
let state = ModuleInstanceState.NonInstantiated;
for (const specifier of (node as ExportDeclaration).exportClause!.elements) {
const specifierState = getModuleInstanceStateForAliasTarget(specifier, visited);
if (specifierState > state) {
state = specifierState;
}
if (state === ModuleInstanceState.Instantiated) {
return state;
}
}
return state;
}
break;
// 5. other uninstantiated module declarations.
case SyntaxKind.ModuleBlock: {
let state = ModuleInstanceState.NonInstantiated;
forEachChild(node, n => {
const childState = getModuleInstanceStateWorker(n);
const childState = getModuleInstanceStateCached(n, visited);
switch (childState) {
case ModuleInstanceState.NonInstantiated:
// child is non-instantiated - continue searching
@ -61,7 +92,7 @@ namespace ts {
return state;
}
case SyntaxKind.ModuleDeclaration:
return getModuleInstanceState(node as ModuleDeclaration);
return getModuleInstanceState(node as ModuleDeclaration, visited);
case SyntaxKind.Identifier:
// Only jsdoc typedef definition can exist in jsdoc namespace, and it should
// be considered the same as type alias
@ -72,6 +103,36 @@ namespace ts {
return ModuleInstanceState.Instantiated;
}
function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: Map<ModuleInstanceState | undefined>) {
const name = specifier.propertyName || specifier.name;
let p: Node | undefined = specifier.parent;
while (p) {
if (isBlock(p) || isModuleBlock(p) || isSourceFile(p)) {
const statements = p.statements;
let found: ModuleInstanceState | undefined;
for (const statement of statements) {
if (nodeHasName(statement, name)) {
if (!statement.parent) {
setParentPointers(p, statement);
}
const state = getModuleInstanceStateCached(statement, visited);
if (found === undefined || state > found) {
found = state;
}
if (found === ModuleInstanceState.Instantiated) {
return found;
}
}
}
if (found !== undefined) {
return found;
}
}
p = p.parent;
}
return ModuleInstanceState.Instantiated; // Couldn't locate, assume could refer to a value
}
const enum ContainerFlags {
// The current node is not a container, and no container manipulation should happen before
// recursing into it.
@ -2561,7 +2622,7 @@ namespace ts {
// Declare a 'member' if the container is an ES5 class or ES6 constructor
constructorSymbol.members = constructorSymbol.members || createSymbolTable();
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, SymbolFlags.Class);
}
break;
@ -2575,7 +2636,7 @@ namespace ts {
// Bind this property to the containing class
const containingClass = thisContainer.parent;
const symbolTable = hasModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports! : containingClass.symbol.members!;
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true);
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true);
break;
case SyntaxKind.SourceFile:
// this.property = assignment in a source file -- declare symbol in exports for a module, in locals for a script

File diff suppressed because it is too large Load Diff

View File

@ -873,6 +873,13 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Disable_strict_checking_of_generic_signatures_in_function_types,
},
{
name: "useDefineForClassFields",
type: "boolean",
affectsSemanticDiagnostics: true,
category: Diagnostics.Advanced_Options,
description: Diagnostics.Emit_class_fields_with_Define_instead_of_Set,
},
{
name: "keyofStringsOnly",
type: "boolean",

View File

@ -329,6 +329,21 @@ namespace ts {
return undefined;
}
/**
* Like `forEach`, but iterates in reverse order.
*/
export function forEachRight<T, U>(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
if (array) {
for (let i = array.length - 1; i >= 0; i--) {
const result = callback(array[i], i);
if (result) {
return result;
}
}
}
return undefined;
}
/** Like `forEach`, but suitable for use with numbers and strings (which may be falsy). */
export function firstDefined<T, U>(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
if (array === undefined) {
@ -1537,6 +1552,14 @@ namespace ts {
return fn ? fn.bind(obj) : undefined;
}
export function mapMap<T, U>(map: Map<T>, f: (t: T, key: string) => [string, U]): Map<U>;
export function mapMap<T, U>(map: UnderscoreEscapedMap<T>, f: (t: T, key: __String) => [string, U]): Map<U>;
export function mapMap<T, U>(map: Map<T> | UnderscoreEscapedMap<T>, f: ((t: T, key: string) => [string, U]) | ((t: T, key: __String) => [string, U])): Map<U> {
const result = createMap<U>();
map.forEach((t: T, key: string & __String) => result.set(...(f(t, key))));
return result;
}
export interface MultiMap<T> extends Map<T[]> {
/**
* Adds the value to an array of values associated with the key, and returns the array.
@ -2159,8 +2182,19 @@ namespace ts {
return (arg: T) => f(arg) && g(arg);
}
export function or<T>(f: (arg: T) => boolean, g: (arg: T) => boolean): (arg: T) => boolean {
return arg => f(arg) || g(arg);
export function or<T extends unknown>(...fs: ((arg: T) => boolean)[]): (arg: T) => boolean {
return arg => {
for (const f of fs) {
if (f(arg)) {
return true;
}
}
return false;
};
}
export function not<T extends unknown[]>(fn: (...args: T) => boolean): (...args: T) => boolean {
return (...args) => !fn(...args);
}
export function assertType<T>(_: T): void { }

View File

@ -2233,6 +2233,19 @@
"category": "Error",
"code": 2609
},
"Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member property.": {
"category": "Error",
"code": 2610
},
"Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member accessor.": {
"category": "Error",
"code": 2611
},
"Property '{0}' will overwrite the base property in '{1}'. If this is intentional, add an initializer. Otherwise, add a 'declare' modifier or remove the redundant declaration.": {
"category": "Error",
"code": 2612
},
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
"category": "Error",
"code": 2649
@ -3112,6 +3125,10 @@
"category": "Error",
"code": 5047
},
"Option '{0}' cannot be specified when option 'target' is 'ES3'.": {
"category": "Error",
"code": 5048
},
"Option '{0} can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.": {
"category": "Error",
"code": 5051
@ -3966,6 +3983,10 @@
"Conflicts are in this file.": {
"category": "Message",
"code": 6201
},
"Project references may not form a circular graph. Cycle detected: {0}": {
"category": "Error",
"code": 6202
},
"'{0}' was also declared here.": {
"category": "Message",
@ -4043,6 +4064,10 @@
"category": "Message",
"code": 6221
},
"Emit class fields with Define instead of Set.": {
"category": "Message",
"code": 6222
},
"Projects to reference": {
"category": "Message",
@ -4052,10 +4077,7 @@
"category": "Message",
"code": 6302
},
"Project references may not form a circular graph. Cycle detected: {0}": {
"category": "Error",
"code": 6202
},
"Composite projects may not disable declaration emit.": {
"category": "Error",
"code": 6304
@ -4565,6 +4587,14 @@
"category": "Error",
"code": 9004
},
"Declaration emit for this file requires using private name '{0}'. An explicit type annotation may unblock declaration emit.": {
"category": "Error",
"code": 9005
},
"Declaration emit for this file requires using private name '{0}' from module '{1}'. An explicit type annotation may unblock declaration emit.": {
"category": "Error",
"code": 9006
},
"JSX attributes must only be assigned a non-empty 'expression'.": {
"category": "Error",
"code": 17000
@ -5180,6 +5210,14 @@
"category": "Message",
"code": 95093
},
"Prefix with 'declare'": {
"category": "Message",
"code": 95094
},
"Prefix all incorrect property declarations with 'declare'": {
"category": "Message",
"code": 95095
},
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
"category": "Error",

View File

@ -96,9 +96,7 @@ namespace ts {
comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo;
const jsFilePath = options.emitDeclarationOnly || isJsonEmittedToSameLocation ? undefined : ownOutputFilePath;
const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options);
// For legacy reasons (ie, we have baselines capturing the behavior), js files don't report a .d.ts output path - this would only matter if `declaration` and `allowJs` were both on, which is currently an error
const isJs = isSourceFileJS(sourceFile);
const declarationFilePath = ((forceDtsPaths || getEmitDeclarations(options)) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath: undefined };
}
@ -146,7 +144,7 @@ namespace ts {
/* @internal */
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts) && hasTSFileExtension(inputFileName));
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts));
return changeExtension(
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.declarationDir || configFile.options.outDir),
Extension.Dts
@ -199,7 +197,7 @@ namespace ts {
if (js && configFile.options.sourceMap) {
addOutput(`${js}.map`);
}
if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) {
if (getEmitDeclarations(configFile.options)) {
const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
addOutput(dts);
if (configFile.options.declarationMap) {
@ -248,7 +246,7 @@ namespace ts {
const jsFilePath = getOutputJSFileName(inputFileName, configFile, ignoreCase);
if (jsFilePath) return jsFilePath;
if (fileExtensionIs(inputFileName, Extension.Json)) continue;
if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) {
if (getEmitDeclarations(configFile.options)) {
return getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
}
}
@ -395,17 +393,16 @@ namespace ts {
declarationFilePath: string | undefined,
declarationMapPath: string | undefined,
relativeToBuildInfo: (path: string) => string) {
if (!sourceFileOrBundle || !(declarationFilePath && !isInJSFile(sourceFileOrBundle))) {
if (!sourceFileOrBundle || !declarationFilePath) {
return;
}
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
// Setup and perform the transformation to retrieve declarations from the input files
const nonJsFiles = filter(sourceFiles, isSourceFileNotJS);
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles;
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(sourceFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : sourceFiles;
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
nonJsFiles.forEach(collectLinkedAliases);
sourceFiles.forEach(collectLinkedAliases);
}
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false);
if (length(declarationTransform.diagnostics)) {
@ -659,6 +656,7 @@ namespace ts {
getAllAccessorDeclarations: notImplemented,
getSymbolOfExternalModuleSpecifier: notImplemented,
isBindingCapturedByNode: notImplemented,
getDeclarationStatementsForSourceFile: notImplemented,
};
/*@internal*/

View File

@ -484,6 +484,47 @@ namespace ts {
return node;
}
function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) {
return createCall(
createPropertyAccess(object, asName(methodName)),
/*typeArguments*/ undefined,
argumentsList
);
}
function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) {
return createMethodCall(createIdentifier(globalObjectName), methodName, argumentsList);
}
/* @internal */
export function createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression) {
return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]);
}
function tryAddPropertyAssignment(properties: Push<PropertyAssignment>, propertyName: string, expression: Expression | undefined) {
if (expression) {
properties.push(createPropertyAssignment(propertyName, expression));
return true;
}
return false;
}
/* @internal */
export function createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean) {
const properties: PropertyAssignment[] = [];
tryAddPropertyAssignment(properties, "enumerable", asExpression(attributes.enumerable));
tryAddPropertyAssignment(properties, "configurable", asExpression(attributes.configurable));
let isData = tryAddPropertyAssignment(properties, "writable", asExpression(attributes.writable));
isData = tryAddPropertyAssignment(properties, "value", attributes.value) || isData;
let isAccessor = tryAddPropertyAssignment(properties, "get", attributes.get);
isAccessor = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor;
Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor.");
return createObjectLiteral(properties, !singleLine);
}
export function updateMethod(
node: MethodDeclaration,
decorators: readonly Decorator[] | undefined,
@ -2218,6 +2259,11 @@ namespace ts {
: node;
}
/* @internal */
export function createEmptyExports() {
return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined);
}
export function createNamedExports(elements: readonly ExportSpecifier[]) {
const node = <NamedExports>createSynthesizedNode(SyntaxKind.NamedExports);
node.elements = createNodeArray(elements);
@ -3146,8 +3192,11 @@ namespace ts {
return isString(name) ? createIdentifier(name) : name;
}
function asExpression(value: string | number | Expression) {
return isString(value) || typeof value === "number" ? createLiteral(value) : value;
function asExpression<T extends Expression | undefined>(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral {
return typeof value === "string" ? createStringLiteral(value) :
typeof value === "number" ? createNumericLiteral(""+value) :
typeof value === "boolean" ? value ? createTrue() : createFalse() :
value;
}
function asNodeArray<T extends Node>(array: readonly T[]): NodeArray<T>;

View File

@ -5995,8 +5995,16 @@ namespace ts {
token() === SyntaxKind.NumericLiteral ||
token() === SyntaxKind.AsteriskToken ||
token() === SyntaxKind.OpenBracketToken) {
return parsePropertyOrMethodDeclaration(<PropertyDeclaration | MethodDeclaration>node);
const isAmbient = node.modifiers && some(node.modifiers, isDeclareModifier);
if (isAmbient) {
for (const m of node.modifiers!) {
m.flags |= NodeFlags.Ambient;
}
return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(node as PropertyDeclaration | MethodDeclaration));
}
else {
return parsePropertyOrMethodDeclaration(node as PropertyDeclaration | MethodDeclaration);
}
}
if (node.decorators || node.modifiers) {

View File

@ -856,7 +856,7 @@ namespace ts {
}
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
for (const fileName of parsedRef.commandLine.fileNames) {
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
if (!fileExtensionIs(fileName, Extension.Dts)) {
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
}
}
@ -2448,8 +2448,8 @@ namespace ts {
}
function getProjectReferenceRedirectProject(fileName: string) {
// Ignore dts or any of the non ts files
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts) || !fileExtensionIsOneOf(fileName, supportedTSExtensions)) {
// Ignore dts
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts)) {
return undefined;
}
@ -2510,7 +2510,7 @@ namespace ts {
}
else {
forEach(resolvedRef.commandLine.fileNames, fileName => {
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
if (!fileExtensionIs(fileName, Extension.Dts)) {
const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, host.useCaseSensitiveFileNames());
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName);
}
@ -3073,8 +3073,8 @@ namespace ts {
}
}
if (!options.noEmit && options.allowJs && getEmitDeclarations(options)) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", getEmitDeclarationOptionName(options));
if (options.useDefineForClassFields && languageVersion === ScriptTarget.ES3) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_target_is_ES3, "useDefineForClassFields");
}
if (options.checkJs && !options.allowJs) {
@ -3421,9 +3421,6 @@ namespace ts {
return resolveConfigFileProjectName(passedInRef.path);
}
function getEmitDeclarationOptionName(options: CompilerOptions) {
return options.declaration ? "declaration" : "composite";
}
/* @internal */
/**
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.

View File

@ -44,7 +44,9 @@ namespace ts {
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
const options = context.getCompilerOptions();
if (node.isDeclarationFile
|| options.useDefineForClassFields && options.target === ScriptTarget.ESNext) {
return node;
}
const visited = visitEachChild(node, visitor, context);
@ -172,9 +174,9 @@ namespace ts {
// From ES6 specification:
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const staticProperties = getProperties(node, /*requireInitializer*/ true, /*isStatic*/ true);
if (some(staticProperties)) {
addInitializedPropertyStatements(statements, staticProperties, getInternalName(node));
addPropertyStatements(statements, staticProperties, getInternalName(node));
}
return statements;
@ -196,7 +198,7 @@ namespace ts {
// these statements after the class expression variable statement.
const isDecoratedClassDeclaration = isClassDeclaration(getOriginalNode(node));
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const staticProperties = getProperties(node, /*requireInitializer*/ true, /*isStatic*/ true);
const extendsClauseElement = getEffectiveBaseTypeNode(node);
const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword);
@ -220,7 +222,7 @@ namespace ts {
pendingExpressions = savedPendingExpressions;
if (pendingStatements && some(staticProperties)) {
addInitializedPropertyStatements(pendingStatements, staticProperties, getInternalName(node));
addPropertyStatements(pendingStatements, staticProperties, getInternalName(node));
}
return classExpression;
}
@ -266,8 +268,8 @@ namespace ts {
function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration);
const containsPropertyInitializer = forEach(node.members, isInitializedProperty);
if (!containsPropertyInitializer) {
const containsProperty = forEach(node.members, m => isInitializedProperty(m, /*requireInitializer*/ !context.getCompilerOptions().useDefineForClassFields));
if (!containsProperty) {
return constructor;
}
const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context);
@ -292,7 +294,7 @@ namespace ts {
}
function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) {
const properties = getInitializedProperties(node, /*isStatic*/ false);
const properties = getProperties(node, /*requireInitializer*/ !context.getCompilerOptions().useDefineForClassFields, /*isStatic*/ false);
// Only generate synthetic constructor when there are property initializers to move.
if (!constructor && !some(properties)) {
@ -349,7 +351,7 @@ namespace ts {
indexOfFirstStatement += parameterPropertyDeclarationCount;
}
}
addInitializedPropertyStatements(statements, properties, createThis());
addPropertyStatements(statements, properties, createThis());
// Add existing statements, skipping the initial super call.
if (constructor) {
@ -376,7 +378,7 @@ namespace ts {
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function addInitializedPropertyStatements(statements: Statement[], properties: readonly PropertyDeclaration[], receiver: LeftHandSideExpression) {
function addPropertyStatements(statements: Statement[], properties: readonly PropertyDeclaration[], receiver: LeftHandSideExpression) {
for (const property of properties) {
const statement = createExpressionStatement(transformInitializedProperty(property, receiver));
setSourceMapRange(statement, moveRangePastModifiers(property));
@ -414,13 +416,23 @@ namespace ts {
*/
function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) {
// We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
const emitAssignment = !context.getCompilerOptions().useDefineForClassFields;
const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression)
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name))
: property.name;
const initializer = visitNode(property.initializer, visitor, isExpression);
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
return createAssignment(memberAccess, initializer);
const initializer = property.initializer || emitAssignment ? visitNode(property.initializer, visitor, isExpression) : createVoidZero();
if (emitAssignment) {
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
return createAssignment(memberAccess, initializer);
}
else {
const name = isComputedPropertyName(propertyName) ? propertyName.expression
: isIdentifier(propertyName) ? createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText))
: propertyName;
const descriptor = createPropertyDescriptor({ value: initializer, configurable: true, writable: true, enumerable: true });
return createObjectDefinePropertyCall(receiver, name, descriptor);
}
}
function enableSubstitutionForClassAliases() {

View File

@ -1,11 +1,8 @@
/*@internal*/
namespace ts {
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined {
if (file && isSourceFileJS(file)) {
return []; // No declaration diagnostics for js for now
}
const compilerOptions = host.getCompilerOptions();
const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJS), [transformDeclarations], /*allowDtsFiles*/ false);
const result = transformNodes(resolver, host, compilerOptions, file ? [file] : host.getSourceFiles(), [transformDeclarations], /*allowDtsFiles*/ false);
return result.diagnostics;
}
@ -86,7 +83,6 @@ namespace ts {
let emittedImports: readonly AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass
const resolver = context.getEmitResolver();
const options = context.getCompilerOptions();
const newLine = getNewLineCharacter(options);
const { noResolve, stripInternal } = options;
return transformRoot;
@ -191,15 +187,24 @@ namespace ts {
}
}
function createEmptyExports() {
return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined);
function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) {
const oldDiag = getSymbolAccessibilityDiagnostic;
getSymbolAccessibilityDiagnostic = (s) => ({
diagnosticMessage: s.errorModuleName
? Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit
: Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit,
errorNode: s.errorNode || sourceFile
});
const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker, bundled);
getSymbolAccessibilityDiagnostic = oldDiag;
return result;
}
function transformRoot(node: Bundle): Bundle;
function transformRoot(node: SourceFile): SourceFile;
function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle;
function transformRoot(node: SourceFile | Bundle) {
if (node.kind === SyntaxKind.SourceFile && (node.isDeclarationFile || isSourceFileJS(node))) {
if (node.kind === SyntaxKind.SourceFile && node.isDeclarationFile) {
return node;
}
@ -210,7 +215,7 @@ namespace ts {
let hasNoDefaultLib = false;
const bundle = createBundle(map(node.sourceFiles,
sourceFile => {
if (sourceFile.isDeclarationFile || isSourceFileJS(sourceFile)) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
if (sourceFile.isDeclarationFile) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib;
currentSourceFile = sourceFile;
enclosingDeclaration = sourceFile;
@ -222,10 +227,10 @@ namespace ts {
resultHasScopeMarker = false;
collectReferences(sourceFile, refs);
collectLibs(sourceFile, libs);
if (isExternalModule(sourceFile)) {
if (isExternalOrCommonJsModule(sourceFile) || isJsonSourceFile(sourceFile)) {
resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
needsDeclare = false;
const statements = visitNodes(sourceFile.statements, visitDeclarationStatements);
const statements = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
const newFile = updateSourceFileNode(sourceFile, [createModuleDeclaration(
[],
[createModifier(SyntaxKind.DeclareKeyword)],
@ -235,7 +240,7 @@ namespace ts {
return newFile;
}
needsDeclare = true;
const updated = visitNodes(sourceFile.statements, visitDeclarationStatements);
const updated = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
return updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []);
}
), mapDefined(node.prepends, prepend => {
@ -277,12 +282,19 @@ namespace ts {
const references: FileReference[] = [];
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
const statements = visitNodes(node.statements, visitDeclarationStatements);
let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
refs.forEach(referenceVisitor);
emittedImports = filter(combinedStatements, isAnyImportSyntax);
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements);
let combinedStatements: NodeArray<Statement>;
if (isSourceFileJS(currentSourceFile)) {
combinedStatements = createNodeArray(transformDeclarationsForJS(node));
emittedImports = filter(combinedStatements, isAnyImportSyntax);
}
else {
const statements = visitNodes(node.statements, visitDeclarationStatements);
combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
refs.forEach(referenceVisitor);
emittedImports = filter(combinedStatements, isAnyImportSyntax);
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements);
}
}
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
@ -756,15 +768,6 @@ namespace ts {
}
}
function isExternalModuleIndicator(result: LateVisibilityPaintedStatement | ExportAssignment) {
// Exported top-level member indicates moduleness
return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export);
}
function needsScopeMarker(result: LateVisibilityPaintedStatement | ExportAssignment) {
return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result);
}
function visitDeclarationSubtree(input: Node): VisitResult<Node> {
if (shouldStripInternal(input)) return;
if (isDeclaration(input)) {
@ -861,35 +864,25 @@ namespace ts {
return cleanup(sig);
}
case SyntaxKind.GetAccessor: {
// For now, only emit class accessors as accessors if they were already declared in an ambient context.
if (input.flags & NodeFlags.Ambient) {
const isPrivate = hasModifier(input, ModifierFlags.Private);
const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
return cleanup(updateGetAccessor(
input,
/*decorators*/ undefined,
ensureModifiers(input),
input.name,
updateAccessorParamsList(input, isPrivate),
!isPrivate ? ensureType(input, accessorType) : undefined,
/*body*/ undefined));
}
const newNode = ensureAccessor(input);
return cleanup(newNode);
const isPrivate = hasModifier(input, ModifierFlags.Private);
const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
return cleanup(updateGetAccessor(
input,
/*decorators*/ undefined,
ensureModifiers(input),
input.name,
updateAccessorParamsList(input, isPrivate),
!isPrivate ? ensureType(input, accessorType) : undefined,
/*body*/ undefined));
}
case SyntaxKind.SetAccessor: {
// For now, only emit class accessors as accessors if they were already declared in an ambient context.
if (input.flags & NodeFlags.Ambient) {
return cleanup(updateSetAccessor(
input,
/*decorators*/ undefined,
ensureModifiers(input),
input.name,
updateAccessorParamsList(input, hasModifier(input, ModifierFlags.Private)),
/*body*/ undefined));
}
const newNode = ensureAccessor(input);
return cleanup(newNode);
return cleanup(updateSetAccessor(
input,
/*decorators*/ undefined,
ensureModifiers(input),
input.name,
updateAccessorParamsList(input, hasModifier(input, ModifierFlags.Private)),
/*body*/ undefined));
}
case SyntaxKind.PropertyDeclaration:
return cleanup(updateProperty(
@ -1462,36 +1455,6 @@ namespace ts {
return accessorType;
}
function ensureAccessor(node: AccessorDeclaration): PropertyDeclaration | undefined {
const accessors = resolver.getAllAccessorDeclarations(node);
if (node.kind !== accessors.firstAccessor.kind) {
return;
}
const accessorType = getTypeAnnotationFromAllAccessorDeclarations(node, accessors);
const prop = createProperty(/*decorators*/ undefined, maskModifiers(node, /*mask*/ undefined, (!accessors.setAccessor) ? ModifierFlags.Readonly : ModifierFlags.None), node.name, node.questionToken, ensureType(node, accessorType), /*initializer*/ undefined);
const leadingsSyntheticCommentRanges = accessors.secondAccessor && getLeadingCommentRangesOfNode(accessors.secondAccessor, currentSourceFile);
if (leadingsSyntheticCommentRanges) {
for (const range of leadingsSyntheticCommentRanges) {
if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
let text = currentSourceFile.text.slice(range.pos + 2, range.end - 2);
const lines = text.split(/\r\n?|\n/g);
if (lines.length > 1) {
const lastLines = lines.slice(1);
const indentation = guessIndentation(lastLines);
text = [lines[0], ...map(lastLines, l => l.slice(indentation))].join(newLine);
}
addSyntheticLeadingComment(
prop,
range.kind,
text,
range.hasTrailingNewLine
);
}
}
}
return prop;
}
function transformHeritageClauses(nodes: NodeArray<HeritageClause> | undefined) {
return createNodeArray(filter(map(nodes, clause => updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => {
return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword);

View File

@ -1591,17 +1591,22 @@ namespace ts {
function transformClassMethodDeclarationToStatement(receiver: LeftHandSideExpression, member: MethodDeclaration, container: Node) {
const commentRange = getCommentRange(member);
const sourceMapRange = getSourceMapRange(member);
const memberName = createMemberAccessForPropertyName(receiver, visitNode(member.name, visitor, isPropertyName), /*location*/ member.name);
const memberFunction = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined, container);
let e: Expression;
if (context.getCompilerOptions().useDefineForClassFields) {
const propertyName = visitNode(member.name, visitor, isPropertyName);
const name = isComputedPropertyName(propertyName) ? propertyName.expression
: isIdentifier(propertyName) ? createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText))
: propertyName;
e = createObjectDefinePropertyCall(receiver, name, createPropertyDescriptor({ value: memberFunction, enumerable: false, writable: true, configurable: true }));
}
else {
const memberName = createMemberAccessForPropertyName(receiver, visitNode(member.name, visitor, isPropertyName), /*location*/ member.name);
e = createAssignment(memberName, memberFunction);
}
setEmitFlags(memberFunction, EmitFlags.NoComments);
setSourceMapRange(memberFunction, sourceMapRange);
const statement = setTextRange(
createExpressionStatement(
createAssignment(memberName, memberFunction)
),
/*location*/ member
);
const statement = setTextRange(createExpressionStatement(e), /*location*/ member);
setOriginalNode(statement, member);
setCommentRange(statement, commentRange);

View File

@ -610,7 +610,7 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const staticProperties = getProperties(node, /*requireInitializer*/ true, /*isStatic*/ true);
const facts = getClassFacts(node, staticProperties);
if (facts & ClassFacts.UseImmediatelyInvokedFunctionExpression) {

View File

@ -297,41 +297,29 @@ namespace ts {
}
/**
* Gets all property declarations with initializers on either the static or instance side of a class.
* Gets all the static or all the instance property declarations of a class
*
* @param node The class node.
* @param isStatic A value indicating whether to get properties from the static or instance side of the class.
*/
export function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): readonly PropertyDeclaration[] {
return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty);
export function getProperties(node: ClassExpression | ClassDeclaration, requireInitializer: boolean, isStatic: boolean): readonly PropertyDeclaration[] {
return filter(node.members, m => isInitializedOrStaticProperty(m, requireInitializer, isStatic)) as PropertyDeclaration[];
}
/**
* Gets a value indicating whether a class element is a static property declaration with an initializer.
*
* @param member The class element node.
*/
export function isStaticInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } {
return isInitializedProperty(member) && hasStaticModifier(member);
}
/**
* Gets a value indicating whether a class element is an instance property declaration with an initializer.
*
* @param member The class element node.
*/
export function isInstanceInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } {
return isInitializedProperty(member) && !hasStaticModifier(member);
}
/**
* Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer.
* Is a class element either a static or an instance property declaration with an initializer?
*
* @param member The class element node.
* @param isStatic A value indicating whether the member should be a static or instance member.
*/
export function isInitializedProperty(member: ClassElement): member is PropertyDeclaration & { initializer: Expression; } {
return member.kind === SyntaxKind.PropertyDeclaration
&& (<PropertyDeclaration>member).initializer !== undefined;
function isInitializedOrStaticProperty(member: ClassElement, requireInitializer: boolean, isStatic: boolean) {
return isPropertyDeclaration(member)
&& (!!member.initializer || !requireInitializer)
&& hasStaticModifier(member) === isStatic;
}
}
export function isInitializedProperty(member: ClassElement, requireInitializer: boolean): member is PropertyDeclaration {
return isPropertyDeclaration(member) && (!!member.initializer || !requireInitializer);
}
}

View File

@ -3734,6 +3734,7 @@ namespace ts {
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined;
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker, bundled?: boolean): Statement[] | undefined;
}
export const enum SymbolFlags {
@ -3814,6 +3815,12 @@ namespace ts {
ClassMember = Method | Accessor | Property,
/* @internal */
ExportSupportsDefaultModifier = Class | Function | Interface,
/* @internal */
ExportDoesNotSupportDefaultModifier = ~ExportSupportsDefaultModifier,
/* @internal */
// The set of things we consider semantically classifiable. Used to speed up the LS during
// classification.
@ -3877,6 +3884,7 @@ namespace ts {
variances?: VarianceFlags[]; // Alias symbol type argument variance cache
deferralConstituents?: Type[]; // Calculated list of constituents for a deferred type
deferralParent?: Type; // Source union/intersection of a deferred type
cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target
}
/* @internal */
@ -4870,6 +4878,7 @@ namespace ts {
/*@internal*/ watch?: boolean;
esModuleInterop?: boolean;
/* @internal */ showConfig?: boolean;
useDefineForClassFields?: boolean;
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
}
@ -5572,6 +5581,16 @@ namespace ts {
readonly redirectTargetsMap: RedirectTargetsMap;
}
/* @internal */
export interface PropertyDescriptorAttributes {
enumerable?: boolean | Expression;
configurable?: boolean | Expression;
writable?: boolean | Expression;
value?: Expression;
get?: Expression;
set?: Expression;
}
export interface TransformationContext {
/*@internal*/ getEmitResolver(): EmitResolver;
/*@internal*/ getEmitHost(): EmitHost;
@ -6013,7 +6032,7 @@ namespace ts {
// Called when the symbol writer encounters a symbol to write. Currently only used by the
// declaration emitter to help determine if it should patch up the final declaration file
// with import statements it previously saw (but chose not to emit).
trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
trackSymbol?(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags): void;
reportInaccessibleThisError?(): void;
reportPrivateInBaseOfClassExpression?(propertyName: string): void;
reportInaccessibleUniqueSymbolError?(): void;

View File

@ -2606,6 +2606,8 @@ namespace ts {
// export = <EntityNameExpression>
// export default <EntityNameExpression>
// module.exports = <EntityNameExpression>
// {<Identifier>}
// {name: <EntityNameExpression>}
export function isAliasSymbolDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.NamespaceExportDeclaration ||
@ -2614,12 +2616,28 @@ namespace ts {
node.kind === SyntaxKind.ImportSpecifier ||
node.kind === SyntaxKind.ExportSpecifier ||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node) ||
isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node);
isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node) ||
isPropertyAccessExpression(node) && isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAliasableExpression(node.parent.right) ||
node.kind === SyntaxKind.ShorthandPropertyAssignment ||
node.kind === SyntaxKind.PropertyAssignment && isAliasableExpression((node as PropertyAssignment).initializer);
}
function isAliasableExpression(e: Expression) {
return isEntityNameExpression(e) || isClassExpression(e);
}
export function exportAssignmentIsAlias(node: ExportAssignment | BinaryExpression): boolean {
const e = isExportAssignment(node) ? node.expression : node.right;
return isEntityNameExpression(e) || isClassExpression(e);
const e = getExportAssignmentExpression(node);
return isAliasableExpression(e);
}
export function getExportAssignmentExpression(node: ExportAssignment | BinaryExpression): Expression {
return isExportAssignment(node) ? node.expression : node.right;
}
export function getPropertyAssignmentAliasLikeExpression(node: PropertyAssignment | ShorthandPropertyAssignment | PropertyAccessExpression): Expression {
return node.kind === SyntaxKind.ShorthandPropertyAssignment ? node.name : node.kind === SyntaxKind.PropertyAssignment ? node.initializer :
(node.parent as BinaryExpression).right;
}
export function getEffectiveBaseTypeNode(node: ClassLikeDeclaration | InterfaceDeclaration) {
@ -2699,6 +2717,11 @@ namespace ts {
return token !== undefined && isNonContextualKeyword(token);
}
export function isStringAKeyword(name: string) {
const token = stringToToken(name);
return token !== undefined && isKeyword(token);
}
export function isIdentifierANonContextualKeyword({ originalKeywordKind }: Identifier): boolean {
return !!originalKeywordKind && !isContextualKeyword(originalKeywordKind);
}
@ -3380,11 +3403,7 @@ namespace ts {
};
}
export interface TrailingSemicolonDeferringWriter extends EmitTextWriter {
resetPendingTrailingSemicolon(): void;
}
export function getTrailingSemicolonDeferringWriter(writer: EmitTextWriter): TrailingSemicolonDeferringWriter {
export function getTrailingSemicolonDeferringWriter(writer: EmitTextWriter): EmitTextWriter {
let pendingTrailingSemicolon = false;
function commitPendingTrailingSemicolon() {
@ -3451,28 +3470,20 @@ namespace ts {
commitPendingTrailingSemicolon();
writer.decreaseIndent();
},
resetPendingTrailingSemicolon() {
pendingTrailingSemicolon = false;
}
};
}
export function getTrailingSemicolonOmittingWriter(writer: EmitTextWriter): EmitTextWriter {
const deferringWriter = getTrailingSemicolonDeferringWriter(writer);
return {
...deferringWriter,
writeLine() {
deferringWriter.resetPendingTrailingSemicolon();
writer.writeLine();
},
};
export interface ResolveModuleNameResolutionHost {
getCanonicalFileName(p: string): string;
getCommonSourceDirectory(): string;
getCurrentDirectory(): string;
}
export function getResolvedExternalModuleName(host: EmitHost, file: SourceFile, referenceFile?: SourceFile): string {
export function getResolvedExternalModuleName(host: ResolveModuleNameResolutionHost, file: SourceFile, referenceFile?: SourceFile): string {
return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName);
}
export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined {
export function getExternalModuleNameFromDeclaration(host: ResolveModuleNameResolutionHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined {
const file = resolver.getExternalModuleFileFromDeclaration(declaration);
if (!file || file.isDeclarationFile) {
return undefined;
@ -3483,7 +3494,7 @@ namespace ts {
/**
* Resolves a local path to a path which is absolute to the base of the emit
*/
export function getExternalModuleNameFromPath(host: EmitHost, fileName: string, referencePath?: string): string {
export function getExternalModuleNameFromPath(host: ResolveModuleNameResolutionHost, fileName: string, referencePath?: string): string {
const getCanonicalFileName = (f: string) => host.getCanonicalFileName(f);
const dir = toPath(referencePath ? getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
const filePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
@ -3974,7 +3985,6 @@ namespace ts {
}
export function getModifierFlagsNoCache(node: Node): ModifierFlags {
let flags = ModifierFlags.None;
if (node.modifiers) {
for (const modifier of node.modifiers) {
@ -5243,6 +5253,17 @@ namespace ts {
return name && isIdentifier(name) ? name : undefined;
}
/** @internal */
export function nodeHasName(statement: Node, name: Identifier) {
if (isNamedDeclaration(statement) && isIdentifier(statement.name) && idText(statement.name as Identifier) === idText(name)) {
return true;
}
if (isVariableStatement(statement) && some(statement.declarationList.declarations, d => nodeHasName(d, name))) {
return true;
}
return false;
}
export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
return declaration.name || nameForNamelessJSDocTypedef(declaration);
}
@ -6164,7 +6185,7 @@ namespace ts {
return node.kind === SyntaxKind.JSDocTypeExpression;
}
export function isJSDocAllType(node: JSDocAllType): node is JSDocAllType {
export function isJSDocAllType(node: Node): node is JSDocAllType {
return node.kind === SyntaxKind.JSDocAllType;
}
@ -6781,6 +6802,27 @@ namespace ts {
return false;
}
/* @internal */
export function isScopeMarker(node: Node) {
return isExportAssignment(node) || isExportDeclaration(node);
}
/* @internal */
export function hasScopeMarker(statements: readonly Statement[]) {
return some(statements, isScopeMarker);
}
/* @internal */
export function needsScopeMarker(result: Statement) {
return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result);
}
/* @internal */
export function isExternalModuleIndicator(result: Statement) {
// Exported top-level member indicates moduleness
return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export);
}
/* @internal */
export function isForInOrOfStatement(node: Node): node is ForInOrOfStatement {
return node.kind === SyntaxKind.ForInStatement || node.kind === SyntaxKind.ForOfStatement;

View File

@ -219,14 +219,19 @@ namespace compiler {
return vpath.changeExtension(path, ext);
}
public getNumberOfJsFiles() {
let count = this.js.size;
this.js.forEach(document => {
if (ts.fileExtensionIs(document.file, ts.Extension.Json)) {
count--;
}
});
return count;
public getNumberOfJsFiles(includeJson: boolean) {
if (includeJson) {
return this.js.size;
}
else {
let count = this.js.size;
this.js.forEach(document => {
if (ts.fileExtensionIs(document.file, ts.Extension.Json)) {
count--;
}
});
return count;
}
}
}

View File

@ -1683,7 +1683,7 @@ namespace FourSlash {
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
offset += this.applyEdits(this.activeFile.fileName, edits);
}
}
}
@ -1756,7 +1756,7 @@ namespace FourSlash {
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
offset += this.applyEdits(this.activeFile.fileName, edits);
}
}
}
@ -1775,7 +1775,7 @@ namespace FourSlash {
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeSettings);
if (edits.length) {
this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.applyEdits(this.activeFile.fileName, edits);
}
}
@ -1810,9 +1810,7 @@ namespace FourSlash {
* @returns The number of characters added to the file as a result of the edits.
* May be negative.
*/
private applyEdits(fileName: string, edits: readonly ts.TextChange[], isFormattingEdit: boolean): number {
// Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters
const oldContent = this.getFileContent(fileName);
private applyEdits(fileName: string, edits: readonly ts.TextChange[]): number {
let runningOffset = 0;
forEachTextChange(edits, edit => {
@ -1833,14 +1831,6 @@ namespace FourSlash {
runningOffset += editDelta;
});
if (isFormattingEdit) {
const newContent = this.getFileContent(fileName);
if (this.removeWhitespace(newContent) !== this.removeWhitespace(oldContent)) {
this.raiseError("Formatting operation destroyed non-whitespace content");
}
}
return runningOffset;
}
@ -1856,17 +1846,17 @@ namespace FourSlash {
public formatDocument() {
const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeSettings);
this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.applyEdits(this.activeFile.fileName, edits);
}
public formatSelection(start: number, end: number) {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeSettings);
this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.applyEdits(this.activeFile.fileName, edits);
}
public formatOnType(pos: number, key: string) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeSettings);
this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.applyEdits(this.activeFile.fileName, edits);
}
private editScriptAndUpdateMarkers(fileName: string, editStart: number, editEnd: number, newText: string) {
@ -2414,7 +2404,7 @@ namespace FourSlash {
if (options.applyChanges) {
for (const change of action.changes) {
this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false);
this.applyEdits(change.fileName, change.textChanges);
}
this.verifyNewContentAfterChange(options, action.changes.map(c => c.fileName));
}
@ -2497,7 +2487,7 @@ namespace FourSlash {
private applyChanges(changes: readonly ts.FileTextChanges[]): void {
for (const change of changes) {
this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false);
this.applyEdits(change.fileName, change.textChanges);
}
}
@ -2525,7 +2515,7 @@ namespace FourSlash {
ts.Debug.assert(codeFix.changes.length === 1);
const change = ts.first(codeFix.changes);
ts.Debug.assert(change.fileName === fileName);
this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false);
this.applyEdits(change.fileName, change.textChanges);
const text = range ? this.rangeText(range) : this.getFileContent(this.activeFile.fileName);
actualTextArray.push(text);
scriptInfo.updateContent(originalContent);
@ -2929,7 +2919,7 @@ namespace FourSlash {
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, this.formatCodeSettings, range, refactorName, actionName, ts.emptyOptions)!;
for (const edit of editInfo.edits) {
this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false);
this.applyEdits(edit.fileName, edit.textChanges);
}
let renameFilename: string | undefined;
@ -3045,7 +3035,7 @@ namespace FourSlash {
const editInfo = this.languageService.getEditsForRefactor(marker.fileName, formattingOptions, marker.position, refactorNameToApply, actionName, ts.emptyOptions)!;
for (const edit of editInfo.edits) {
this.applyEdits(edit.fileName, edit.textChanges, /*isFormattingEdit*/ false);
this.applyEdits(edit.fileName, edit.textChanges);
}
const actualContent = this.getFileContent(marker.fileName);

View File

@ -888,7 +888,7 @@ namespace Harness {
throw new Error("Only declaration files should be generated when emitDeclarationOnly:true");
}
}
else if (result.dts.size !== result.getNumberOfJsFiles()) {
else if (result.dts.size !== result.getNumberOfJsFiles(/*includeJson*/ true)) {
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
}
}
@ -907,7 +907,7 @@ namespace Harness {
if (vpath.isDeclaration(file.unitName) || vpath.isJson(file.unitName)) {
dtsFiles.push(file);
}
else if (vpath.isTypeScript(file.unitName)) {
else if (vpath.isTypeScript(file.unitName) || (vpath.isJavaScript(file.unitName) && options.allowJs)) {
const declFile = findResultCodeFile(file.unitName);
if (declFile && !findUnit(declFile.file, declInputFiles) && !findUnit(declFile.file, declOtherFiles)) {
dtsFiles.push({ unitName: declFile.file, content: utils.removeByteOrderMark(declFile.text) });
@ -1269,7 +1269,7 @@ namespace Harness {
return;
}
else if (options.sourceMap || declMaps) {
if (result.maps.size !== (result.getNumberOfJsFiles() * (declMaps && options.sourceMap ? 2 : 1))) {
if (result.maps.size !== ((options.sourceMap ? result.getNumberOfJsFiles(/*includeJson*/ false) : 0) + (declMaps ? result.getNumberOfJsFiles(/*includeJson*/ true) : 0))) {
throw new Error("Number of sourcemap files should be same as js files.");
}

View File

@ -2956,6 +2956,12 @@ namespace ts.server.protocol {
Smart = "Smart",
}
export enum SemicolonPreference {
Ignore = "ignore",
Insert = "insert",
Remove = "remove",
}
export interface EditorSettings {
baseIndentSize?: number;
indentSize?: number;
@ -2982,6 +2988,7 @@ namespace ts.server.protocol {
placeOpenBraceOnNewLineForFunctions?: boolean;
placeOpenBraceOnNewLineForControlBlocks?: boolean;
insertSpaceBeforeTypeAnnotation?: boolean;
semicolons?: SemicolonPreference;
}
export interface UserPreferences {
@ -3067,6 +3074,7 @@ namespace ts.server.protocol {
strictNullChecks?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
useDefineForClassFields?: boolean;
target?: ScriptTarget | ts.ScriptTarget;
traceResolution?: boolean;
resolveJsonModule?: boolean;

View File

@ -0,0 +1,34 @@
/* @internal */
namespace ts.codefix {
const fixId = "addMissingDeclareProperty";
const errorCodes = [
Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration.code,
];
registerCodeFix({
errorCodes,
getCodeActions: (context) => {
const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start));
if (changes.length > 0) {
return [createCodeFixAction(fixId, changes, Diagnostics.Prefix_with_declare, fixId, Diagnostics.Prefix_all_incorrect_property_declarations_with_declare)];
}
},
fixIds: [fixId],
getAllCodeActions: context => {
const fixedNodes = new NodeSet();
return codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start, fixedNodes));
},
});
function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number, fixedNodes?: NodeSet<Node>) {
const token = getTokenAtPosition(sourceFile, pos);
if (!isIdentifier(token)) {
return;
}
const declaration = token.parent;
if (declaration.kind === SyntaxKind.PropertyDeclaration &&
(!fixedNodes || fixedNodes.tryAdd(declaration))) {
changeTracker.insertModifierBefore(sourceFile, SyntaxKind.DeclareKeyword, declaration);
}
}
}

View File

@ -169,7 +169,7 @@ namespace ts.codefix {
// We sort the best codefixes first, so taking `first` is best for completions.
const moduleSpecifier = first(getNewImportInfos(program, sourceFile, position, exportInfos, host, preferences)).moduleSpecifier;
const fix = first(getFixForImport(exportInfos, symbolName, position, program, sourceFile, host, preferences));
return { moduleSpecifier, codeAction: codeFixActionToCodeAction(codeActionForFix({ host, formatContext }, sourceFile, symbolName, fix, getQuotePreference(sourceFile, preferences))) };
return { moduleSpecifier, codeAction: codeFixActionToCodeAction(codeActionForFix({ host, formatContext, preferences }, sourceFile, symbolName, fix, getQuotePreference(sourceFile, preferences))) };
}
function codeFixActionToCodeAction({ description, changes, commands }: CodeFixAction): CodeAction {

View File

@ -2,16 +2,14 @@
namespace ts.formatting {
export interface FormatContext {
readonly options: FormatCodeSettings;
readonly getRule: RulesMap;
readonly getRules: RulesMap;
}
export interface TextRangeWithKind extends TextRange {
kind: SyntaxKind;
export interface TextRangeWithKind<T extends SyntaxKind = SyntaxKind> extends TextRange {
kind: T;
}
export interface TextRangeWithTriviaKind extends TextRange {
kind: TriviaKind;
}
export type TextRangeWithTriviaKind = TextRangeWithKind<TriviaKind>;
export interface TokenInfo {
leadingTrivia: TextRangeWithTriviaKind[] | undefined;
@ -19,6 +17,16 @@ namespace ts.formatting {
trailingTrivia: TextRangeWithTriviaKind[] | undefined;
}
export function createTextRangeWithKind<T extends SyntaxKind>(pos: number, end: number, kind: T): TextRangeWithKind<T> {
const textRangeWithKind: TextRangeWithKind<T> = { pos, end, kind };
if (Debug.isDebugging) {
Object.defineProperty(textRangeWithKind, "__debugKind", {
get: () => Debug.formatSyntaxKind(kind),
});
}
return textRangeWithKind;
}
const enum Constants {
Unknown = -1
}
@ -386,7 +394,7 @@ namespace ts.formatting {
initialIndentation: number,
delta: number,
formattingScanner: FormattingScanner,
{ options, getRule }: FormatContext,
{ options, getRules }: FormatContext,
requestKind: FormattingRequestKind,
rangeContainsError: (r: TextRange) => boolean,
sourceFile: SourceFileLike): TextChange[] {
@ -469,7 +477,7 @@ namespace ts.formatting {
parent: Node,
parentDynamicIndentation: DynamicIndentation,
effectiveParentStartLine: number
): { indentation: number, delta: number } {
): { indentation: number, delta: number; } {
const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0;
if (effectiveParentStartLine === startLine) {
@ -644,6 +652,21 @@ namespace ts.formatting {
consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation, node);
}
if (!node.parent && formattingScanner.isOnEOF()) {
const token = formattingScanner.readEOFTokenRange();
if (token.end <= node.end && previousRange) {
processPair(
token,
sourceFile.getLineAndCharacterOfPosition(token.pos).line,
node,
previousRange,
previousRangeStartLine,
previousParent,
contextNode,
nodeDynamicIndentation);
}
}
function processChildNode(
child: Node,
inheritedIndentation: number,
@ -938,37 +961,41 @@ namespace ts.formatting {
formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
const rule = getRule(formattingContext);
const rules = getRules(formattingContext);
let trimTrailingWhitespaces: boolean;
let trimTrailingWhitespaces = false;
let lineAction = LineAction.None;
if (rule) {
lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
switch (lineAction) {
case LineAction.LineRemoved:
// Handle the case where the next line is moved to be the end of this line.
// In this case we don't indent the next line in the next pass.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false);
}
break;
case LineAction.LineAdded:
// Handle the case where token2 is moved to the new line.
// In this case we indent token2 in the next pass but we set
// sameLineIndent flag to notify the indenter that the indentation is within the line.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true);
}
break;
default:
Debug.assert(lineAction === LineAction.None);
}
if (rules) {
// Apply rules in reverse order so that higher priority rules (which are first in the array)
// win in a conflict with lower priority rules.
forEachRight(rules, rule => {
lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
switch (lineAction) {
case LineAction.LineRemoved:
// Handle the case where the next line is moved to be the end of this line.
// In this case we don't indent the next line in the next pass.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false);
}
break;
case LineAction.LineAdded:
// Handle the case where token2 is moved to the new line.
// In this case we indent token2 in the next pass but we set
// sameLineIndent flag to notify the indenter that the indentation is within the line.
if (currentParent.getStart(sourceFile) === currentItem.pos) {
dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true);
}
break;
default:
Debug.assert(lineAction === LineAction.None);
}
// We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
trimTrailingWhitespaces = !(rule.action & RuleAction.Delete) && rule.flags !== RuleFlags.CanDeleteNewLines;
// We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
trimTrailingWhitespaces = !(rule.action & RuleAction.DeleteSpace) && rule.flags !== RuleFlags.CanDeleteNewLines;
});
}
else {
trimTrailingWhitespaces = true;
trimTrailingWhitespaces = currentItem.kind !== SyntaxKind.EndOfFileToken;
}
if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) {
@ -1130,6 +1157,12 @@ namespace ts.formatting {
}
}
function recordInsert(start: number, text: string) {
if (text) {
edits.push(createTextChangeFromStartLength(start, 0, text));
}
}
function applyRuleEdits(rule: Rule,
previousRange: TextRangeWithKind,
previousStartLine: number,
@ -1138,17 +1171,20 @@ namespace ts.formatting {
): LineAction {
const onLaterLine = currentStartLine !== previousStartLine;
switch (rule.action) {
case RuleAction.Ignore:
case RuleAction.StopProcessingSpaceActions:
// no action required
return LineAction.None;
case RuleAction.Delete:
case RuleAction.DeleteSpace:
if (previousRange.end !== currentRange.pos) {
// delete characters starting from t1.end up to t2.pos exclusive
recordDelete(previousRange.end, currentRange.pos - previousRange.end);
return onLaterLine ? LineAction.LineRemoved : LineAction.None;
}
break;
case RuleAction.NewLine:
case RuleAction.DeleteToken:
recordDelete(previousRange.pos, previousRange.end - previousRange.pos);
break;
case RuleAction.InsertNewLine:
// exit early if we on different lines and rule cannot change number of newlines
// if line1 and line2 are on subsequent lines then no edits are required - ok to exit
// if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines
@ -1163,7 +1199,7 @@ namespace ts.formatting {
return onLaterLine ? LineAction.None : LineAction.LineAdded;
}
break;
case RuleAction.Space:
case RuleAction.InsertSpace:
// exit early if we on different lines and rule cannot change number of newlines
if (rule.flags !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) {
return LineAction.None;
@ -1174,6 +1210,9 @@ namespace ts.formatting {
recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
return onLaterLine ? LineAction.LineRemoved : LineAction.None;
}
break;
case RuleAction.InsertTrailingSemicolon:
recordInsert(previousRange.end, ";");
}
return LineAction.None;
}
@ -1271,7 +1310,7 @@ namespace ts.formatting {
return SyntaxKind.Unknown;
}
let internedSizes: { tabSize: number; indentSize: number };
let internedSizes: { tabSize: number; indentSize: number; };
let internedTabsIndentation: string[] | undefined;
let internedSpacesIndentation: string[] | undefined;

View File

@ -99,4 +99,4 @@ namespace ts.formatting {
return false;
}
}
}
}

View File

@ -6,7 +6,9 @@ namespace ts.formatting {
export interface FormattingScanner {
advance(): void;
isOnToken(): boolean;
isOnEOF(): boolean;
readTokenInfo(n: Node): TokenInfo;
readEOFTokenRange(): TextRangeWithKind;
getCurrentLeadingTrivia(): TextRangeWithKind[] | undefined;
lastTrailingTriviaWasNewLine(): boolean;
skipToEndOf(node: Node): void;
@ -38,7 +40,9 @@ namespace ts.formatting {
const res = cb({
advance,
readTokenInfo,
readEOFTokenRange,
isOnToken,
isOnEOF,
getCurrentLeadingTrivia: () => leadingTrivia,
lastTrailingTriviaWasNewLine: () => wasNewLine,
skipToEndOf,
@ -164,11 +168,11 @@ namespace ts.formatting {
let currentToken = getNextToken(n, expectedScanAction);
const token: TextRangeWithKind = {
pos: scanner.getStartPos(),
end: scanner.getTextPos(),
kind: currentToken
};
const token = createTextRangeWithKind(
scanner.getStartPos(),
scanner.getTextPos(),
currentToken,
);
// consume trailing trivia
if (trailingTrivia) {
@ -179,11 +183,11 @@ namespace ts.formatting {
if (!isTrivia(currentToken)) {
break;
}
const trivia: TextRangeWithTriviaKind = {
pos: scanner.getStartPos(),
end: scanner.getTextPos(),
kind: currentToken
};
const trivia = createTextRangeWithKind(
scanner.getStartPos(),
scanner.getTextPos(),
currentToken,
);
if (!trailingTrivia) {
trailingTrivia = [];
@ -243,12 +247,22 @@ namespace ts.formatting {
return token;
}
function readEOFTokenRange(): TextRangeWithKind<SyntaxKind.EndOfFileToken> {
Debug.assert(isOnEOF());
return createTextRangeWithKind(scanner.getStartPos(), scanner.getTextPos(), SyntaxKind.EndOfFileToken);
}
function isOnToken(): boolean {
const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
const startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
}
function isOnEOF(): boolean {
const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
return current === SyntaxKind.EndOfFileToken;
}
// when containing node in the tree is token
// but its kind differs from the kind that was returned by the scanner,
// then kind needs to be fixed. This might happen in cases

View File

@ -12,10 +12,17 @@ namespace ts.formatting {
export const anyContext: readonly ContextPredicate[] = emptyArray;
export const enum RuleAction {
Ignore = 1 << 0,
Space = 1 << 1,
NewLine = 1 << 2,
Delete = 1 << 3,
StopProcessingSpaceActions = 1 << 0,
StopProcessingTokenActions = 1 << 1,
InsertSpace = 1 << 2,
InsertNewLine = 1 << 3,
DeleteSpace = 1 << 4,
DeleteToken = 1 << 5,
InsertTrailingSemicolon = 1 << 6,
StopAction = StopProcessingSpaceActions | StopProcessingTokenActions,
ModifySpaceAction = InsertSpace | InsertNewLine | DeleteSpace,
ModifyTokenAction = DeleteToken | InsertTrailingSemicolon,
}
export const enum RuleFlags {
@ -27,4 +34,4 @@ namespace ts.formatting {
readonly tokens: readonly SyntaxKind[];
readonly isSpecific: boolean;
}
}
}

View File

@ -9,7 +9,9 @@ namespace ts.formatting {
export function getAllRules(): RuleSpec[] {
const allTokens: SyntaxKind[] = [];
for (let token = SyntaxKind.FirstToken; token <= SyntaxKind.LastToken; token++) {
allTokens.push(token);
if (token !== SyntaxKind.EndOfFileToken) {
allTokens.push(token);
}
}
function anyTokenExcept(...tokens: SyntaxKind[]): TokenRange {
return { tokens: allTokens.filter(t => !tokens.some(t2 => t2 === t)), isSpecific: false };
@ -17,6 +19,7 @@ namespace ts.formatting {
const anyToken: TokenRange = { tokens: allTokens, isSpecific: false };
const anyTokenIncludingMultilineComments = tokenRangeFrom([...allTokens, SyntaxKind.MultiLineCommentTrivia]);
const anyTokenIncludingEOF = tokenRangeFrom([...allTokens, SyntaxKind.EndOfFileToken]);
const keywords = tokenRangeFromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword);
const binaryOperators = tokenRangeFromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator);
const binaryKeywordOperators = [SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.AsKeyword, SyntaxKind.IsKeyword];
@ -44,103 +47,103 @@ namespace ts.formatting {
// These rules are higher in priority than user-configurable
const highPriorityCommonRules = [
// Leave comments alone
rule("IgnoreBeforeComment", anyToken, comments, anyContext, RuleAction.Ignore),
rule("IgnoreAfterLineComment", SyntaxKind.SingleLineCommentTrivia, anyToken, anyContext, RuleAction.Ignore),
rule("IgnoreBeforeComment", anyToken, comments, anyContext, RuleAction.StopProcessingSpaceActions),
rule("IgnoreAfterLineComment", SyntaxKind.SingleLineCommentTrivia, anyToken, anyContext, RuleAction.StopProcessingSpaceActions),
rule("NotSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], RuleAction.Delete),
rule("SpaceAfterColon", SyntaxKind.ColonToken, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Space),
rule("NoSpaceBeforeQuestionMark", anyToken, SyntaxKind.QuestionToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete),
rule("NotSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], RuleAction.DeleteSpace),
rule("SpaceAfterColon", SyntaxKind.ColonToken, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.InsertSpace),
rule("NoSpaceBeforeQuestionMark", anyToken, SyntaxKind.QuestionToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.DeleteSpace),
// insert space after '?' only when it is used in conditional operator
rule("SpaceAfterQuestionMarkInConditionalOperator", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], RuleAction.Space),
rule("SpaceAfterQuestionMarkInConditionalOperator", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], RuleAction.InsertSpace),
// in other cases there should be no space between '?' and next token
rule("NoSpaceAfterQuestionMark", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterQuestionMark", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeDot", anyToken, SyntaxKind.DotToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterDot", SyntaxKind.DotToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeDot", anyToken, SyntaxKind.DotToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterDot", SyntaxKind.DotToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBetweenImportParenInImportType", SyntaxKind.ImportKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isImportTypeContext], RuleAction.Delete),
rule("NoSpaceBetweenImportParenInImportType", SyntaxKind.ImportKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isImportTypeContext], RuleAction.DeleteSpace),
// Special handling of unary operators.
// Prefix operators generally shouldn't have a space between
// them and their target unary expression.
rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete),
rule("NoSpaceAfterUnaryPreincrementOperator", SyntaxKind.PlusPlusToken, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterUnaryPredecrementOperator", SyntaxKind.MinusMinusToken, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterUnaryPreincrementOperator", SyntaxKind.PlusPlusToken, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterUnaryPredecrementOperator", SyntaxKind.MinusMinusToken, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// More unary operator special-casing.
// DevDiv 181814: Be careful when removing leading whitespace
// around unary operators. Examples:
// 1 - -2 --X--> 1--2
// a + ++b --X--> a+++b
rule("SpaceAfterPostincrementWhenFollowedByAdd", SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterAddWhenFollowedByUnaryPlus", SyntaxKind.PlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterAddWhenFollowedByPreincrement", SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterPostdecrementWhenFollowedBySubtract", SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", SyntaxKind.MinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterSubtractWhenFollowedByPredecrement", SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterPostincrementWhenFollowedByAdd", SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterAddWhenFollowedByUnaryPlus", SyntaxKind.PlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterAddWhenFollowedByPreincrement", SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterPostdecrementWhenFollowedBySubtract", SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", SyntaxKind.MinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterSubtractWhenFollowedByPredecrement", SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("NoSpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, [SyntaxKind.CommaToken, SyntaxKind.SemicolonToken], [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, [SyntaxKind.CommaToken, SyntaxKind.SemicolonToken], [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// For functions and control block place } on a new line [multi-line rule]
rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, SyntaxKind.CloseBraceToken, [isMultilineBlockContext], RuleAction.NewLine),
rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, SyntaxKind.CloseBraceToken, [isMultilineBlockContext], RuleAction.InsertNewLine),
// Space/new line after }.
rule("SpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, anyTokenExcept(SyntaxKind.CloseParenToken), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], RuleAction.Space),
rule("SpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, anyTokenExcept(SyntaxKind.CloseParenToken), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], RuleAction.InsertSpace),
// Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied
// Also should not apply to })
rule("SpaceBetweenCloseBraceAndElse", SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBetweenCloseBraceAndWhile", SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.Delete),
rule("SpaceBetweenCloseBraceAndElse", SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceBetweenCloseBraceAndWhile", SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.DeleteSpace),
// Add a space after control dec context if the next character is an open bracket ex: 'if (false)[a, b] = [1, 2];' -> 'if (false) [a, b] = [1, 2];'
rule("SpaceAfterConditionalClosingParen", SyntaxKind.CloseParenToken, SyntaxKind.OpenBracketToken, [isControlDeclContext], RuleAction.Space),
rule("SpaceAfterConditionalClosingParen", SyntaxKind.CloseParenToken, SyntaxKind.OpenBracketToken, [isControlDeclContext], RuleAction.InsertSpace),
rule("NoSpaceBetweenFunctionKeywordAndStar", SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.Delete),
rule("SpaceAfterStarInGeneratorDeclaration", SyntaxKind.AsteriskToken, SyntaxKind.Identifier, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.Space),
rule("NoSpaceBetweenFunctionKeywordAndStar", SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.DeleteSpace),
rule("SpaceAfterStarInGeneratorDeclaration", SyntaxKind.AsteriskToken, SyntaxKind.Identifier, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.InsertSpace),
rule("SpaceAfterFunctionInFuncDecl", SyntaxKind.FunctionKeyword, anyToken, [isFunctionDeclContext], RuleAction.Space),
rule("SpaceAfterFunctionInFuncDecl", SyntaxKind.FunctionKeyword, anyToken, [isFunctionDeclContext], RuleAction.InsertSpace),
// Insert new line after { and before } in multi-line contexts.
rule("NewLineAfterOpenBraceInBlockContext", SyntaxKind.OpenBraceToken, anyToken, [isMultilineBlockContext], RuleAction.NewLine),
rule("NewLineAfterOpenBraceInBlockContext", SyntaxKind.OpenBraceToken, anyToken, [isMultilineBlockContext], RuleAction.InsertNewLine),
// For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token.
// Though, we do extra check on the context to make sure we are dealing with get/set node. Example:
// get x() {}
// set x(val) {}
rule("SpaceAfterGetSetInMember", [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword], SyntaxKind.Identifier, [isFunctionDeclContext], RuleAction.Space),
rule("SpaceAfterGetSetInMember", [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword], SyntaxKind.Identifier, [isFunctionDeclContext], RuleAction.InsertSpace),
rule("NoSpaceBetweenYieldKeywordAndStar", SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.Delete),
rule("SpaceBetweenYieldOrYieldStarAndOperand", [SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.Space),
rule("NoSpaceBetweenYieldKeywordAndStar", SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.DeleteSpace),
rule("SpaceBetweenYieldOrYieldStarAndOperand", [SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.InsertSpace),
rule("NoSpaceBetweenReturnAndSemicolon", SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceAfterCertainKeywords", [SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword, SyntaxKind.AwaitKeyword], anyToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceAfterLetConstInVariableDeclaration", [SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], RuleAction.Space),
rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], RuleAction.Delete),
rule("NoSpaceBetweenReturnAndSemicolon", SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("SpaceAfterCertainKeywords", [SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword, SyntaxKind.AwaitKeyword], anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceAfterLetConstInVariableDeclaration", [SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], RuleAction.InsertSpace),
rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], RuleAction.DeleteSpace),
// Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options.
rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterVoidOperator", SyntaxKind.VoidKeyword, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], RuleAction.Space),
rule("SpaceAfterVoidOperator", SyntaxKind.VoidKeyword, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], RuleAction.InsertSpace),
// Async-await
rule("SpaceBetweenAsyncAndOpenParen", SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken, [isArrowFunctionContext, isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBetweenAsyncAndFunctionKeyword", SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBetweenAsyncAndOpenParen", SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken, [isArrowFunctionContext, isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceBetweenAsyncAndFunctionKeyword", SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
// Template string
rule("NoSpaceBetweenTagAndTemplateString", [SyntaxKind.Identifier, SyntaxKind.CloseParenToken], [SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead], [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBetweenTagAndTemplateString", [SyntaxKind.Identifier, SyntaxKind.CloseParenToken], [SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead], [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// JSX opening elements
rule("SpaceBeforeJsxAttribute", anyToken, SyntaxKind.Identifier, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, SyntaxKind.SlashToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, SyntaxKind.EqualsToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterEqualInJsxAttribute", SyntaxKind.EqualsToken, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceBeforeJsxAttribute", anyToken, SyntaxKind.Identifier, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, SyntaxKind.SlashToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, SyntaxKind.EqualsToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterEqualInJsxAttribute", SyntaxKind.EqualsToken, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// TypeScript-specific rules
// Use of module as a function call. e.g.: import m2 = module("m2");
rule("NoSpaceAfterModuleImport", [SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword], SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterModuleImport", [SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword], SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// Add a space around certain TypeScript keywords
rule(
"SpaceAfterCertainTypeScriptKeywords",
@ -171,41 +174,41 @@ namespace ts.formatting {
],
anyToken,
[isNonJsxSameLineTokenContext],
RuleAction.Space),
RuleAction.InsertSpace),
rule(
"SpaceBeforeCertainTypeScriptKeywords",
anyToken,
[SyntaxKind.ExtendsKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.FromKeyword],
[isNonJsxSameLineTokenContext],
RuleAction.Space),
RuleAction.InsertSpace),
// Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
rule("SpaceAfterModuleName", SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken, [isModuleDeclContext], RuleAction.Space),
rule("SpaceAfterModuleName", SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken, [isModuleDeclContext], RuleAction.InsertSpace),
// Lambda expressions
rule("SpaceBeforeArrow", anyToken, SyntaxKind.EqualsGreaterThanToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceAfterArrow", SyntaxKind.EqualsGreaterThanToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBeforeArrow", anyToken, SyntaxKind.EqualsGreaterThanToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceAfterArrow", SyntaxKind.EqualsGreaterThanToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
// Optional parameters and let args
rule("NoSpaceAfterEllipsis", SyntaxKind.DotDotDotToken, SyntaxKind.Identifier, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterOptionalParameters", SyntaxKind.QuestionToken, [SyntaxKind.CloseParenToken, SyntaxKind.CommaToken], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete),
rule("NoSpaceAfterEllipsis", SyntaxKind.DotDotDotToken, SyntaxKind.Identifier, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterOptionalParameters", SyntaxKind.QuestionToken, [SyntaxKind.CloseParenToken, SyntaxKind.CommaToken], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.DeleteSpace),
// Remove spaces in empty interface literals. e.g.: x: {}
rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectTypeContext], RuleAction.Delete),
rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectTypeContext], RuleAction.DeleteSpace),
// generics and type assertions
rule("NoSpaceBeforeOpenAngularBracket", typeNames, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete),
rule("NoSpaceBetweenCloseParenAndAngularBracket", SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete),
rule("NoSpaceAfterOpenAngularBracket", SyntaxKind.LessThanToken, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete),
rule("NoSpaceBeforeCloseAngularBracket", anyToken, SyntaxKind.GreaterThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete),
rule("NoSpaceBeforeOpenAngularBracket", typeNames, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace),
rule("NoSpaceBetweenCloseParenAndAngularBracket", SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterOpenAngularBracket", SyntaxKind.LessThanToken, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeCloseAngularBracket", anyToken, SyntaxKind.GreaterThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterCloseAngularBracket",
SyntaxKind.GreaterThanToken,
[SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken],
[isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext /*To prevent an interference with the SpaceBeforeOpenParenInFuncDecl rule*/],
RuleAction.Delete),
RuleAction.DeleteSpace),
// decorators
rule("SpaceBeforeAt", [SyntaxKind.CloseParenToken, SyntaxKind.Identifier], SyntaxKind.AtToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceAfterAt", SyntaxKind.AtToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceBeforeAt", [SyntaxKind.CloseParenToken, SyntaxKind.Identifier], SyntaxKind.AtToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("NoSpaceAfterAt", SyntaxKind.AtToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// Insert space after @ in decorator
rule("SpaceAfterDecorator",
anyToken,
@ -225,111 +228,113 @@ namespace ts.formatting {
SyntaxKind.AsteriskToken,
],
[isEndOfDecoratorContextOnSameLine],
RuleAction.Space),
RuleAction.InsertSpace),
rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, SyntaxKind.ExclamationToken, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], RuleAction.Delete),
rule("NoSpaceAfterNewKeywordOnConstructorSignature", SyntaxKind.NewKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], RuleAction.Delete),
rule("SpaceLessThanAndNonJSXTypeAnnotation", SyntaxKind.LessThanToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, SyntaxKind.ExclamationToken, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterNewKeywordOnConstructorSignature", SyntaxKind.NewKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], RuleAction.DeleteSpace),
rule("SpaceLessThanAndNonJSXTypeAnnotation", SyntaxKind.LessThanToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
];
// These rules are applied after high priority
const userConfigurableRules = [
// Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses
rule("SpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("NoSpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], RuleAction.Space),
rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], RuleAction.Delete),
rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], RuleAction.InsertSpace),
rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], RuleAction.DeleteSpace),
// Insert space after function keyword for anonymous functions
rule("SpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.Space),
rule("NoSpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.Delete),
rule("SpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.InsertSpace),
rule("NoSpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.DeleteSpace),
// Insert space after keywords in control flow statements
rule("SpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.Space),
rule("NoSpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.Delete),
rule("SpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.InsertSpace),
rule("NoSpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.DeleteSpace),
// Insert space after opening and before closing nonempty parenthesis
rule("SpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBetweenOpenParens", SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceBetweenParens", SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceBetweenOpenParens", SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("NoSpaceBetweenParens", SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// Insert space after opening and before closing nonempty brackets
rule("SpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceBetweenBrackets", SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("NoSpaceBetweenBrackets", SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
rule("SpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.Space),
rule("SpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.Space),
rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.Delete),
rule("NoSpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.InsertSpace),
rule("SpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.InsertSpace),
rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// Insert space after opening and before closing template string braces
rule("SpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("SpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
rule("NoSpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// No space after { and before } in JSX expression
rule("SpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Space),
rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Space),
rule("NoSpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Delete),
rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Delete),
rule("SpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.InsertSpace),
rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.InsertSpace),
rule("NoSpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.DeleteSpace),
rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.DeleteSpace),
// Insert space after semicolon in for statement
rule("SpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.Space),
rule("NoSpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.Delete),
rule("SpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.InsertSpace),
rule("NoSpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.DeleteSpace),
// Insert space before and after binary operators
rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space),
rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Delete),
rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Delete),
rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace),
rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.DeleteSpace),
rule("SpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.Space),
rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.Delete),
rule("SpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.InsertSpace),
rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.DeleteSpace),
// Open Brace braces after control block
rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], RuleAction.NewLine, RuleFlags.CanDeleteNewLines),
rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines),
// Open Brace braces after function
// TypeScript: Function can have return types, which can be made of tons of different token kinds
rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], RuleAction.NewLine, RuleFlags.CanDeleteNewLines),
rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines),
// Open Brace braces after TypeScript module/class/interface
rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], RuleAction.NewLine, RuleFlags.CanDeleteNewLines),
rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines),
rule("SpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.Space),
rule("NoSpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.Delete),
rule("SpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.InsertSpace),
rule("NoSpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.DeleteSpace),
rule("SpaceBeforeTypeAnnotation", anyToken, SyntaxKind.ColonToken, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.Space),
rule("NoSpaceBeforeTypeAnnotation", anyToken, SyntaxKind.ColonToken, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.Delete),
rule("SpaceBeforeTypeAnnotation", anyToken, SyntaxKind.ColonToken, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.InsertSpace),
rule("NoSpaceBeforeTypeAnnotation", anyToken, SyntaxKind.ColonToken, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.DeleteSpace),
rule("NoOptionalSemicolon", SyntaxKind.SemicolonToken, anyTokenIncludingEOF, [optionEquals("semicolons", SemicolonPreference.Remove), isSemicolonDeletionContext], RuleAction.DeleteToken),
rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [optionEquals("semicolons", SemicolonPreference.Insert), isSemicolonInsertionContext], RuleAction.InsertTrailingSemicolon),
];
// These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list.
const lowPriorityCommonRules = [
// Space after keyword but not before ; or : or ?
rule("NoSpaceBeforeSemicolon", anyToken, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeSemicolon", anyToken, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.Space, RuleFlags.CanDeleteNewLines),
rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.Space, RuleFlags.CanDeleteNewLines),
rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.Space, RuleFlags.CanDeleteNewLines),
rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines),
rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines),
rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines),
rule("NoSpaceBeforeComma", anyToken, SyntaxKind.CommaToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceBeforeComma", anyToken, SyntaxKind.CommaToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
// No space before and after indexer `x[]`
rule("NoSpaceBeforeOpenBracket", anyTokenExcept(SyntaxKind.AsyncKeyword, SyntaxKind.CaseKeyword), SyntaxKind.OpenBracketToken, [isNonJsxSameLineTokenContext], RuleAction.Delete),
rule("NoSpaceAfterCloseBracket", SyntaxKind.CloseBracketToken, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], RuleAction.Delete),
rule("SpaceAfterSemicolon", SyntaxKind.SemicolonToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("NoSpaceBeforeOpenBracket", anyTokenExcept(SyntaxKind.AsyncKeyword, SyntaxKind.CaseKeyword), SyntaxKind.OpenBracketToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace),
rule("NoSpaceAfterCloseBracket", SyntaxKind.CloseBracketToken, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], RuleAction.DeleteSpace),
rule("SpaceAfterSemicolon", SyntaxKind.SemicolonToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
// Remove extra space between for and await
rule("SpaceBetweenForAndAwaitKeyword", SyntaxKind.ForKeyword, SyntaxKind.AwaitKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceBetweenForAndAwaitKeyword", SyntaxKind.ForKeyword, SyntaxKind.AwaitKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
// Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
// So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
@ -338,9 +343,9 @@ namespace ts.formatting {
[SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword],
anyToken,
[isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext],
RuleAction.Space),
RuleAction.InsertSpace),
// This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
rule("SpaceAfterTryFinally", [SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword], SyntaxKind.OpenBraceToken, [isNonJsxSameLineTokenContext], RuleAction.Space),
rule("SpaceAfterTryFinally", [SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword], SyntaxKind.OpenBraceToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace),
];
return [
@ -395,6 +400,10 @@ namespace ts.formatting {
/// Contexts
///
function optionEquals<K extends keyof FormatCodeSettings>(optionName: K, optionValue: FormatCodeSettings[K]): (context: FormattingContext) => boolean {
return (context) => context.options && context.options[optionName] === optionValue;
}
function isOptionEnabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean {
return (context) => context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName];
}
@ -780,4 +789,79 @@ namespace ts.formatting {
function isNonNullAssertionContext(context: FormattingContext): boolean {
return context.contextNode.kind === SyntaxKind.NonNullExpression;
}
function isSemicolonDeletionContext(context: FormattingContext): boolean {
let nextTokenKind = context.nextTokenSpan.kind;
let nextTokenStart = context.nextTokenSpan.pos;
if (isTrivia(nextTokenKind)) {
const nextRealToken = context.nextTokenParent === context.currentTokenParent
? findNextToken(
context.currentTokenParent,
findAncestor(context.currentTokenParent, a => !a.parent)!,
context.sourceFile)
: context.nextTokenParent.getFirstToken(context.sourceFile);
if (!nextRealToken) {
return true;
}
nextTokenKind = nextRealToken.kind;
nextTokenStart = nextRealToken.getStart(context.sourceFile);
}
const startLine = context.sourceFile.getLineAndCharacterOfPosition(context.currentTokenSpan.pos).line;
const endLine = context.sourceFile.getLineAndCharacterOfPosition(nextTokenStart).line;
if (startLine === endLine) {
return nextTokenKind === SyntaxKind.CloseBraceToken
|| nextTokenKind === SyntaxKind.EndOfFileToken;
}
if (nextTokenKind === SyntaxKind.SemicolonClassElement ||
nextTokenKind === SyntaxKind.SemicolonToken
) {
return false;
}
if (context.contextNode.kind === SyntaxKind.InterfaceDeclaration ||
context.contextNode.kind === SyntaxKind.TypeAliasDeclaration
) {
// Cant remove semicolon after `foo`; it would parse as a method declaration:
//
// interface I {
// foo;
// (): void
// }
return !isPropertySignature(context.currentTokenParent)
|| !!context.currentTokenParent.type
|| nextTokenKind !== SyntaxKind.OpenParenToken;
}
if (isPropertyDeclaration(context.currentTokenParent)) {
return !context.currentTokenParent.initializer;
}
return context.currentTokenParent.kind !== SyntaxKind.ForStatement
&& context.currentTokenParent.kind !== SyntaxKind.EmptyStatement
&& context.currentTokenParent.kind !== SyntaxKind.SemicolonClassElement
&& nextTokenKind !== SyntaxKind.OpenBracketToken
&& nextTokenKind !== SyntaxKind.OpenParenToken
&& nextTokenKind !== SyntaxKind.PlusToken
&& nextTokenKind !== SyntaxKind.MinusToken
&& nextTokenKind !== SyntaxKind.SlashToken
&& nextTokenKind !== SyntaxKind.RegularExpressionLiteral
&& nextTokenKind !== SyntaxKind.CommaToken
&& nextTokenKind !== SyntaxKind.TemplateExpression
&& nextTokenKind !== SyntaxKind.TemplateHead
&& nextTokenKind !== SyntaxKind.NoSubstitutionTemplateLiteral
&& nextTokenKind !== SyntaxKind.DotToken;
}
function isSemicolonInsertionContext(context: FormattingContext): boolean {
const contextAncestor = findAncestor(context.currentTokenParent, ancestor => {
if (ancestor.end !== context.currentTokenSpan.end) {
return "quit";
}
return syntaxMayBeASICandidate(ancestor.kind);
});
return !!contextAncestor && isASICandidate(contextAncestor, context.sourceFile);
}
}

View File

@ -1,7 +1,7 @@
/* @internal */
namespace ts.formatting {
export function getFormatContext(options: FormatCodeSettings): FormatContext {
return { options, getRule: getRulesMap() };
return { options, getRules: getRulesMap() };
}
let rulesMapCache: RulesMap | undefined;
@ -13,12 +13,46 @@ namespace ts.formatting {
return rulesMapCache;
}
export type RulesMap = (context: FormattingContext) => Rule | undefined;
/**
* For a given rule action, gets a mask of other rule actions that
* cannot be applied at the same position.
*/
function getRuleActionExclusion(ruleAction: RuleAction): RuleAction {
let mask: RuleAction = 0;
if (ruleAction & RuleAction.StopProcessingSpaceActions) {
mask |= RuleAction.ModifySpaceAction;
}
if (ruleAction & RuleAction.StopProcessingTokenActions) {
mask |= RuleAction.ModifyTokenAction;
}
if (ruleAction & RuleAction.ModifySpaceAction) {
mask |= RuleAction.ModifySpaceAction;
}
if (ruleAction & RuleAction.ModifyTokenAction) {
mask |= RuleAction.ModifyTokenAction;
}
return mask;
}
export type RulesMap = (context: FormattingContext) => readonly Rule[] | undefined;
function createRulesMap(rules: readonly RuleSpec[]): RulesMap {
const map = buildMap(rules);
return context => {
const bucket = map[getRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind)];
return bucket && find(bucket, rule => every(rule.context, c => c(context)));
if (bucket) {
const rules: Rule[] = [];
let ruleActionMask: RuleAction = 0;
for (const rule of bucket) {
const acceptRuleActions = ~getRuleActionExclusion(ruleActionMask);
if (rule.action & acceptRuleActions && every(rule.context, c => c(context))) {
rules.push(rule);
ruleActionMask |= rule.action;
}
}
if (rules.length) {
return rules;
}
}
};
}
@ -54,8 +88,8 @@ namespace ts.formatting {
const mapRowLength = SyntaxKind.LastToken + 1;
enum RulesPosition {
IgnoreRulesSpecific = 0,
IgnoreRulesAny = maskBitSize * 1,
StopRulesSpecific = 0,
StopRulesAny = maskBitSize * 1,
ContextRulesSpecific = maskBitSize * 2,
ContextRulesAny = maskBitSize * 3,
NoContextRulesSpecific = maskBitSize * 4,
@ -78,8 +112,8 @@ namespace ts.formatting {
// In order to insert a rule to the end of sub-bucket (3), we get the index by adding
// the values in the bitmap segments 3rd, 2nd, and 1st.
function addRule(rules: Rule[], rule: Rule, specificTokens: boolean, constructionState: number[], rulesBucketIndex: number): void {
const position = rule.action === RuleAction.Ignore ?
specificTokens ? RulesPosition.IgnoreRulesSpecific : RulesPosition.IgnoreRulesAny :
const position = rule.action & RuleAction.StopAction ?
specificTokens ? RulesPosition.StopRulesSpecific : RulesPosition.StopRulesAny :
rule.context !== anyContext ?
specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny :
specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny;

View File

@ -6,14 +6,14 @@ namespace ts {
newFileOrDirPath: string,
host: LanguageServiceHost,
formatContext: formatting.FormatContext,
_preferences: UserPreferences,
preferences: UserPreferences,
sourceMapper: SourceMapper,
): readonly FileTextChanges[] {
const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host);
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
const oldToNew = getPathUpdater(oldFileOrDirPath, newFileOrDirPath, getCanonicalFileName, sourceMapper);
const newToOld = getPathUpdater(newFileOrDirPath, oldFileOrDirPath, getCanonicalFileName, sourceMapper);
return textChanges.ChangeTracker.with({ host, formatContext }, changeTracker => {
return textChanges.ChangeTracker.with({ host, formatContext, preferences }, changeTracker => {
updateTsconfigFiles(program, changeTracker, oldToNew, oldFileOrDirPath, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames);
updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName);
});

View File

@ -12,10 +12,10 @@ namespace ts.OrganizeImports {
formatContext: formatting.FormatContext,
host: LanguageServiceHost,
program: Program,
_preferences: UserPreferences,
preferences: UserPreferences,
) {
const changeTracker = textChanges.ChangeTracker.fromContext({ host, formatContext });
const changeTracker = textChanges.ChangeTracker.fromContext({ host, formatContext, preferences });
const coalesceAndOrganizeImports = (importGroup: readonly ImportDeclaration[]) => coalesceImports(removeUnusedImports(importGroup, sourceFile, program));

View File

@ -99,7 +99,7 @@ namespace ts {
return this._children || (this._children = createChildren(this, sourceFile));
}
public getFirstToken(sourceFile?: SourceFile): Node | undefined {
public getFirstToken(sourceFile?: SourceFileLike): Node | undefined {
this.assertHasRealPosition();
const children = this.getChildren(sourceFile);
if (!children.length) {
@ -112,7 +112,7 @@ namespace ts {
child.getFirstToken(sourceFile);
}
public getLastToken(sourceFile?: SourceFile): Node | undefined {
public getLastToken(sourceFile?: SourceFileLike): Node | undefined {
this.assertHasRealPosition();
const children = this.getChildren(sourceFile);
@ -339,7 +339,6 @@ namespace ts {
}
class TokenObject<TKind extends SyntaxKind> extends TokenOrIdentifierObject implements Token<TKind> {
public symbol!: Symbol;
public kind: TKind;
constructor(kind: TKind, pos: number, end: number) {
@ -349,9 +348,8 @@ namespace ts {
}
class IdentifierObject extends TokenOrIdentifierObject implements Identifier {
public kind!: SyntaxKind.Identifier;
public kind: SyntaxKind.Identifier = SyntaxKind.Identifier;
public escapedText!: __String;
public symbol!: Symbol;
public autoGenerateFlags!: GeneratedIdentifierFlags;
_primaryExpressionBrand: any;
_memberExpressionBrand: any;
@ -541,7 +539,7 @@ namespace ts {
}
class SourceFileObject extends NodeObject implements SourceFile {
public kind!: SyntaxKind.SourceFile;
public kind: SyntaxKind.SourceFile = SyntaxKind.SourceFile;
public _declarationBrand: any;
public fileName!: string;
public path!: Path;

View File

@ -218,6 +218,7 @@ namespace ts.textChanges {
export interface TextChangesContext {
host: LanguageServiceHost;
formatContext: formatting.FormatContext;
preferences: UserPreferences;
}
export type TypeAnnotatable = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature;
@ -831,28 +832,36 @@ namespace ts.textChanges {
return (options.prefix || "") + noIndent + (options.suffix || "");
}
function getFormatCodeSettingsForWriting({ options }: formatting.FormatContext, sourceFile: SourceFile): FormatCodeSettings {
const shouldAutoDetectSemicolonPreference = !options.semicolons || options.semicolons === SemicolonPreference.Ignore;
const shouldRemoveSemicolons = options.semicolons === SemicolonPreference.Remove || shouldAutoDetectSemicolonPreference && !probablyUsesSemicolons(sourceFile);
return {
...options,
semicolons: shouldRemoveSemicolons ? SemicolonPreference.Remove : SemicolonPreference.Ignore,
};
}
/** Note: this may mutate `nodeIn`. */
function getFormattedTextOfNode(nodeIn: Node, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string {
const { node, text } = getNonformattedText(nodeIn, sourceFile, newLineCharacter);
if (validate) validate(node, text);
const { options: formatOptions } = formatContext;
const formatOptions = getFormatCodeSettingsForWriting(formatContext, sourceFile);
const initialIndentation =
indentation !== undefined
? indentation
: formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, prefix === newLineCharacter || getLineStartPositionForPosition(pos, sourceFile) === pos);
if (delta === undefined) {
delta = formatting.SmartIndenter.shouldIndentChildNode(formatContext.options, nodeIn) ? (formatOptions.indentSize || 0) : 0;
delta = formatting.SmartIndenter.shouldIndentChildNode(formatOptions, nodeIn) ? (formatOptions.indentSize || 0) : 0;
}
const file: SourceFileLike = { text, getLineAndCharacterOfPosition(pos) { return getLineAndCharacterOfPosition(this, pos); } };
const changes = formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, formatContext);
const changes = formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, { ...formatContext, options: formatOptions });
return applyChanges(text, changes);
}
/** Note: output node may be mutated input node. */
export function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string, node: Node } {
const omitTrailingSemicolon = !!sourceFile && !probablyUsesSemicolons(sourceFile);
const writer = createWriter(newLineCharacter, omitTrailingSemicolon);
const writer = createWriter(newLineCharacter);
const newLine = newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed;
createPrinter({ newLine, neverAsciiEscape: true }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer);
return { text: writer.getText(), node: assignPositionsToNode(node) };
@ -894,11 +903,11 @@ namespace ts.textChanges {
interface TextChangesWriter extends EmitTextWriter, PrintHandlers {}
function createWriter(newLine: string, omitTrailingSemicolon?: boolean): TextChangesWriter {
function createWriter(newLine: string): TextChangesWriter {
let lastNonTriviaPosition = 0;
const writer = omitTrailingSemicolon ? getTrailingSemicolonOmittingWriter(createTextWriter(newLine)) : createTextWriter(newLine);
const writer = createTextWriter(newLine);
const onEmitNode: PrintHandlers["onEmitNode"] = (hint, node, printCallback) => {
if (node) {
setPos(node, lastNonTriviaPosition);

View File

@ -47,6 +47,7 @@
"codefixes/addConvertToUnknownForNonOverlappingTypes.ts",
"codefixes/addMissingAwait.ts",
"codefixes/addMissingConst.ts",
"codefixes/addMissingDeclareProperty.ts",
"codefixes/addMissingInvocationForDecorator.ts",
"codefixes/addNameToNamelessParameter.ts",
"codefixes/annotateWithTypeFromJSDoc.ts",

View File

@ -17,7 +17,11 @@ namespace ts {
getFullText(sourceFile?: SourceFile): string;
getText(sourceFile?: SourceFile): string;
getFirstToken(sourceFile?: SourceFile): Node | undefined;
/* @internal */
getFirstToken(sourceFile?: SourceFileLike): Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
getLastToken(sourceFile?: SourceFile): Node | undefined;
/* @internal */
getLastToken(sourceFile?: SourceFileLike): Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures
// See ts.forEachChild for documentation.
forEachChild<T>(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined;
}
@ -680,6 +684,12 @@ namespace ts {
Smart = 2,
}
export enum SemicolonPreference {
Ignore = "ignore",
Insert = "insert",
Remove = "remove",
}
/* @deprecated - consider using EditorSettings instead */
export interface EditorOptions {
BaseIndentSize?: number;
@ -738,6 +748,7 @@ namespace ts {
readonly placeOpenBraceOnNewLineForControlBlocks?: boolean;
readonly insertSpaceBeforeTypeAnnotation?: boolean;
readonly indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean;
readonly semicolons?: SemicolonPreference;
}
export function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatCodeSettings {
@ -761,6 +772,7 @@ namespace ts {
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
semicolons: SemicolonPreference.Ignore,
};
}

View File

@ -749,7 +749,7 @@ namespace ts {
return findPrecedingToken(position, file);
}
export function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFile): Node | undefined {
export function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFileLike): Node | undefined {
return find(parent);
function find(n: Node): Node | undefined {
@ -757,7 +757,7 @@ namespace ts {
// this is token that starts at the end of previous token - return it
return n;
}
return firstDefined(n.getChildren(), child => {
return firstDefined(n.getChildren(sourceFile), child => {
const shouldDiveInChildNode =
// previous token is enclosed somewhere in the child
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
@ -1971,8 +1971,7 @@ namespace ts {
const notAccessible = () => { typeIsAccessible = false; };
const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
trackSymbol: (symbol, declaration, meaning) => {
// TODO: GH#18217
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning!, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
},
reportInaccessibleThisError: notAccessible,
reportPrivateInBaseOfClassExpression: notAccessible,
@ -1989,7 +1988,27 @@ namespace ts {
return typeIsAccessible ? res : undefined;
}
export function syntaxUsuallyHasTrailingSemicolon(kind: SyntaxKind) {
export function syntaxRequiresTrailingCommaOrSemicolonOrASI(kind: SyntaxKind) {
return kind === SyntaxKind.CallSignature
|| kind === SyntaxKind.ConstructSignature
|| kind === SyntaxKind.IndexSignature
|| kind === SyntaxKind.PropertySignature
|| kind === SyntaxKind.MethodSignature;
}
export function syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI(kind: SyntaxKind) {
return kind === SyntaxKind.FunctionDeclaration
|| kind === SyntaxKind.Constructor
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor;
}
export function syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(kind: SyntaxKind) {
return kind === SyntaxKind.ModuleDeclaration;
}
export function syntaxRequiresTrailingSemicolonOrASI(kind: SyntaxKind) {
return kind === SyntaxKind.VariableStatement
|| kind === SyntaxKind.ExpressionStatement
|| kind === SyntaxKind.DoStatement
@ -2002,7 +2021,58 @@ namespace ts {
|| kind === SyntaxKind.TypeAliasDeclaration
|| kind === SyntaxKind.ImportDeclaration
|| kind === SyntaxKind.ImportEqualsDeclaration
|| kind === SyntaxKind.ExportDeclaration;
|| kind === SyntaxKind.ExportDeclaration
|| kind === SyntaxKind.NamespaceExportDeclaration
|| kind === SyntaxKind.ExportAssignment;
}
export const syntaxMayBeASICandidate = or(
syntaxRequiresTrailingCommaOrSemicolonOrASI,
syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI,
syntaxRequiresTrailingModuleBlockOrSemicolonOrASI,
syntaxRequiresTrailingSemicolonOrASI);
export function isASICandidate(node: Node, sourceFile: SourceFileLike): boolean {
const lastToken = node.getLastToken(sourceFile);
if (lastToken && lastToken.kind === SyntaxKind.SemicolonToken) {
return false;
}
if (syntaxRequiresTrailingCommaOrSemicolonOrASI(node.kind)) {
if (lastToken && lastToken.kind === SyntaxKind.CommaToken) {
return false;
}
}
else if (syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(node.kind)) {
const lastChild = last(node.getChildren(sourceFile));
if (lastChild && isModuleBlock(lastChild)) {
return false;
}
}
else if (syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI(node.kind)) {
const lastChild = last(node.getChildren(sourceFile));
if (lastChild && isFunctionBlock(lastChild)) {
return false;
}
}
else if (!syntaxRequiresTrailingSemicolonOrASI(node.kind)) {
return false;
}
// See comment in parsers `parseDoStatement`
if (node.kind === SyntaxKind.DoStatement) {
return true;
}
const topNode = findAncestor(node, ancestor => !ancestor.parent)!;
const nextToken = findNextToken(node, topNode, sourceFile);
if (!nextToken || nextToken.kind === SyntaxKind.CloseBraceToken) {
return true;
}
const startLine = sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
const endLine = sourceFile.getLineAndCharacterOfPosition(nextToken.getStart(sourceFile)).line;
return startLine !== endLine;
}
export function probablyUsesSemicolons(sourceFile: SourceFile): boolean {
@ -2010,7 +2080,7 @@ namespace ts {
let withoutSemicolon = 0;
const nStatementsToObserve = 5;
forEachChild(sourceFile, function visit(node): boolean | undefined {
if (syntaxUsuallyHasTrailingSemicolon(node.kind)) {
if (syntaxRequiresTrailingSemicolonOrASI(node.kind)) {
const lastToken = node.getLastToken(sourceFile);
if (lastToken && lastToken.kind === SyntaxKind.SemicolonToken) {
withSemicolon++;

View File

@ -24,9 +24,7 @@ namespace Harness.Parallel.Host {
let totalCost = 0;
class RemoteSuite extends Mocha.Suite {
suites!: RemoteSuite[];
suiteMap = ts.createMap<RemoteSuite>();
tests!: RemoteTest[];
constructor(title: string) {
super(title);
this.pending = false;
@ -529,10 +527,10 @@ namespace Harness.Parallel.Host {
function replaySuite(runner: Mocha.Runner, suite: RemoteSuite) {
runner.emit("suite", suite);
for (const test of suite.tests) {
replayTest(runner, test);
replayTest(runner, test as RemoteTest);
}
for (const child of suite.suites) {
replaySuite(runner, child);
replaySuite(runner, child as RemoteSuite);
}
runner.emit("suite end", suite);
}

View File

@ -99,6 +99,7 @@
"unittests/tsbuild/emptyFiles.ts",
"unittests/tsbuild/graphOrdering.ts",
"unittests/tsbuild/inferredTypeFromTransitiveModule.ts",
"unittests/tsbuild/javascriptProjectEmit.ts",
"unittests/tsbuild/lateBoundSymbol.ts",
"unittests/tsbuild/missingExtendedFile.ts",
"unittests/tsbuild/moduleSpecifiers.ts",

View File

@ -0,0 +1,286 @@
namespace ts {
describe("unittests:: tsbuild:: javascriptProjectEmit:: loads js-based projects and emits them correctly", () => {
verifyTsc({
scenario: "javascriptProjectEmit",
subScenario: `loads js-based projects and emits them correctly`,
fs: () => loadProjectFromFiles({
"/src/common/nominal.js": utils.dedent`
/**
* @template T, Name
* @typedef {T & {[Symbol.species]: Name}} Nominal
*/
module.exports = {};
`,
"/src/common/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true
},
"include": ["nominal.js"]
}`,
"/src/sub-project/index.js": utils.dedent`
import { Nominal } from '../common/nominal';
/**
* @typedef {Nominal<string, 'MyNominal'>} MyNominal
*/
`,
"/src/sub-project/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true
},
"references": [
{ "path": "../common" }
],
"include": ["./index.js"]
}`,
"/src/sub-project-2/index.js": utils.dedent`
import { MyNominal } from '../sub-project/index';
const variable = {
key: /** @type {MyNominal} */('value'),
};
/**
* @return {keyof typeof variable}
*/
export function getVar() {
return 'key';
}
`,
"/src/sub-project-2/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true
},
"references": [
{ "path": "../sub-project" }
],
"include": ["./index.js"]
}`,
"/src/tsconfig.json": utils.dedent`
{
"compilerOptions": {
"composite": true
},
"references": [
{ "path": "./sub-project" },
{ "path": "./sub-project-2" }
],
"include": []
}`,
"/src/tsconfig.base.json": utils.dedent`
{
"compilerOptions": {
"skipLibCheck": true,
"rootDir": "./",
"outDir": "../lib",
"allowJs": true,
"checkJs": true,
"declaration": true
}
}`,
}, symbolLibContent),
commandLineArgs: ["-b", "/src"]
});
});
describe("unittests:: tsbuild:: javascriptProjectEmit:: loads outfile js projects and concatenates them correctly", () => {
let projFs: vfs.FileSystem;
before(() => {
projFs = loadProjectFromFiles({
"/src/common/nominal.js": utils.dedent`
/**
* @template T, Name
* @typedef {T & {[Symbol.species]: Name}} Nominal
*/
`,
"/src/common/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outFile": "common.js"
},
"include": ["nominal.js"]
}`,
"/src/sub-project/index.js": utils.dedent`
/**
* @typedef {Nominal<string, 'MyNominal'>} MyNominal
*/
const c = /** @type {*} */(null);
`,
"/src/sub-project/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outFile": "sub-project.js"
},
"references": [
{ "path": "../common", "prepend": true }
],
"include": ["./index.js"]
}`,
"/src/sub-project-2/index.js": utils.dedent`
const variable = {
key: /** @type {MyNominal} */('value'),
};
/**
* @return {keyof typeof variable}
*/
function getVar() {
return 'key';
}
`,
"/src/sub-project-2/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outFile": "sub-project-2.js"
},
"references": [
{ "path": "../sub-project", "prepend": true }
],
"include": ["./index.js"]
}`,
"/src/tsconfig.json": utils.dedent`
{
"compilerOptions": {
"composite": true,
"outFile": "src.js"
},
"references": [
{ "path": "./sub-project", "prepend": true },
{ "path": "./sub-project-2", "prepend": true }
],
"include": []
}`,
"/src/tsconfig.base.json": utils.dedent`
{
"compilerOptions": {
"skipLibCheck": true,
"rootDir": "./",
"allowJs": true,
"checkJs": true,
"declaration": true
}
}`,
}, symbolLibContent);
});
after(() => {
projFs = undefined!;
});
verifyTsc({
scenario: "javascriptProjectEmit",
subScenario: `loads outfile js projects and concatenates them correctly`,
fs: () => projFs,
commandLineArgs: ["-b", "/src"]
});
verifyTscIncrementalEdits({
scenario: "javascriptProjectEmit",
subScenario: `modifies outfile js projects and concatenates them correctly`,
fs: () => projFs,
commandLineArgs: ["-b", "/src"],
incrementalScenarios: [{
buildKind: BuildKind.IncrementalDtsUnchanged,
modifyFs: fs => replaceText(fs, "/src/sub-project/index.js", "null", "undefined")
}]
});
});
describe("unittests:: tsbuild:: javascriptProjectEmit:: loads js-based projects with non-moved json files and emits them correctly", () => {
verifyTsc({
scenario: "javascriptProjectEmit",
subScenario: `loads js-based projects with non-moved json files and emits them correctly`,
fs: () => loadProjectFromFiles({
"/src/common/obj.json": utils.dedent`
{
"val": 42
}`,
"/src/common/index.ts": utils.dedent`
import x = require("./obj.json");
export = x;
`,
"/src/common/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": null
"composite": true
},
"include": ["index.ts", "obj.json"]
}`,
"/src/sub-project/index.js": utils.dedent`
import mod from '../common';
export const m = mod;
`,
"/src/sub-project/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true
},
"references": [
{ "path": "../common" }
],
"include": ["./index.js"]
}`,
"/src/sub-project-2/index.js": utils.dedent`
import { m } from '../sub-project/index';
const variable = {
key: m,
};
export function getVar() {
return variable;
}
`,
"/src/sub-project-2/tsconfig.json": utils.dedent`
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"composite": true
},
"references": [
{ "path": "../sub-project" }
],
"include": ["./index.js"]
}`,
"/src/tsconfig.json": utils.dedent`
{
"compilerOptions": {
"composite": true
},
"references": [
{ "path": "./sub-project" },
{ "path": "./sub-project-2" }
],
"include": []
}`,
"/src/tsconfig.base.json": utils.dedent`
{
"compilerOptions": {
"skipLibCheck": true,
"rootDir": "./",
"outDir": "../out",
"allowJs": true,
"checkJs": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"declaration": true
}
}`,
}, symbolLibContent),
commandLineArgs: ["-b", "/src"]
});
});
}

View File

@ -52,7 +52,12 @@ namespace ts {
export default hello.hello`);
const allExpectedOutputs = ["/src/dist/src/index.js", "/src/dist/src/index.d.ts", "/src/dist/src/index.json"];
verifyProjectWithResolveJsonModuleWithFs(fs, "/src/tsconfig_withIncludeOfJson.json", allExpectedOutputs);
verifyProjectWithResolveJsonModuleWithFs(
fs,
"/src/tsconfig_withIncludeOfJson.json",
allExpectedOutputs,
errorDiagnostic([Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, "/src/dist/src/index.d.ts"])
);
});
it("with resolveJsonModule and files containing json file", () => {

View File

@ -885,8 +885,8 @@ namespace ts.tscWatch {
// More comment`;
const configFileContentAfterComment = `
"compilerOptions": {
"allowJs": true,
"declaration": true
"inlineSourceMap": true,
"mapRoot": "./"
}
}`;
const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment;
@ -900,8 +900,9 @@ namespace ts.tscWatch {
const host = createWatchedSystem(files);
const watch = createWatchOfConfigFile(configFile.path, host);
const errors = () => [
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"),
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"inlineSourceMap"'), '"inlineSourceMap"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"),
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"mapRoot"'), '"mapRoot"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"),
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"mapRoot"'), '"mapRoot"'.length, Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "mapRoot", "sourceMap", "declarationMap")
];
const intialErrors = errors();
checkOutputErrorsInitial(host, intialErrors);

View File

@ -292,7 +292,7 @@ namespace ts.projectSystem {
export class TestSession extends server.Session {
private seq = 0;
public events: protocol.Event[] = [];
public host!: TestServerHost;
public testhost: TestServerHost = this.host as TestServerHost;
getProjectService() {
return this.projectService;
@ -320,7 +320,7 @@ namespace ts.projectSystem {
public clearMessages() {
clear(this.events);
this.host.clearOutput();
this.testhost.clearOutput();
}
}
@ -721,8 +721,8 @@ namespace ts.projectSystem {
const events = session.events;
assert.deepEqual(events[index], expectedEvent, `Expected ${JSON.stringify(expectedEvent)} at ${index} in ${JSON.stringify(events)}`);
const outputs = session.host.getOutput();
assert.equal(outputs[index], server.formatMessage(expectedEvent, nullLogger, Utils.byteLength, session.host.newLine));
const outputs = session.testhost.getOutput();
assert.equal(outputs[index], server.formatMessage(expectedEvent, nullLogger, Utils.byteLength, session.testhost.newLine));
if (isMostRecent) {
assert.strictEqual(events.length, index + 1, JSON.stringify(events));

View File

@ -849,8 +849,8 @@ declare module '@custom/plugin' {
// comment`;
const configFileContentAfterComment = `
"compilerOptions": {
"allowJs": true,
"declaration": true
"inlineSourceMap": true,
"mapRoot": "./"
}
}`;
const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment;
@ -874,7 +874,7 @@ declare module '@custom/plugin' {
seq: 2,
arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true }
}).response as readonly server.protocol.DiagnosticWithLinePosition[];
assert.isTrue(diags.length === 2);
assert.isTrue(diags.length === 3);
configFile.content = configFileContentWithoutCommentLine;
host.reloadFS([file, configFile]);
@ -885,10 +885,11 @@ declare module '@custom/plugin' {
seq: 2,
arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true }
}).response as readonly server.protocol.DiagnosticWithLinePosition[];
assert.isTrue(diagsAfterEdit.length === 2);
assert.isTrue(diagsAfterEdit.length === 3);
verifyDiagnostic(diags[0], diagsAfterEdit[0]);
verifyDiagnostic(diags[1], diagsAfterEdit[1]);
verifyDiagnostic(diags[2], diagsAfterEdit[2]);
function verifyDiagnostic(beforeEditDiag: server.protocol.DiagnosticWithLinePosition, afterEditDiag: server.protocol.DiagnosticWithLinePosition) {
assert.equal(beforeEditDiag.message, afterEditDiag.message);

View File

@ -159,7 +159,7 @@ new C();`
}
});
const host = session.host;
const host = session.testhost;
host.checkTimeoutQueueLengthAndRun(1);
checkErrorMessage(session, "syntaxDiag", { file: recognizersDateTimeSrcFile.path, diagnostics: [] });
@ -219,7 +219,7 @@ new C();`
const projectService = session.getProjectService();
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!;
checkProjectActualFiles(project, filesInProjectWithResolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithResolvedModule, watchedDirectoriesWithResolvedModule, nonRecursiveWatchedDirectories);
verifyWatchedFilesAndDirectories(session.testhost, filesInProjectWithResolvedModule, watchedDirectoriesWithResolvedModule, nonRecursiveWatchedDirectories);
verifyErrors(session, []);
}
@ -227,7 +227,7 @@ new C();`
const projectService = session.getProjectService();
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!;
checkProjectActualFiles(project, filesInProjectWithUnresolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithUnresolvedModule, watchedDirectoriesWithUnresolvedModule, nonRecursiveWatchedDirectories);
verifyWatchedFilesAndDirectories(session.testhost, filesInProjectWithUnresolvedModule, watchedDirectoriesWithUnresolvedModule, nonRecursiveWatchedDirectories);
const startOffset = recognizersDateTimeSrcFile.content.indexOf('"') + 1;
verifyErrors(session, [
createDiagnostic({ line: 1, offset: startOffset }, { line: 1, offset: startOffset + moduleNameInFile.length }, Diagnostics.Cannot_find_module_0, [moduleName])

View File

@ -0,0 +1,13 @@
tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts(5,9): error TS2423: Class 'A' defines instance member function 'm', but extended class 'B' defines it as instance member accessor.
==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts (1 errors) ====
class A {
m() { }
}
class B extends A {
get m() { return () => 1 }
~
!!! error TS2423: Class 'A' defines instance member function 'm', but extended class 'B' defines it as instance member accessor.
}

View File

@ -0,0 +1,16 @@
//// [accessorsOverrideMethod.ts]
class A {
m() { }
}
class B extends A {
get m() { return () => 1 }
}
//// [accessorsOverrideMethod.js]
class A {
m() { }
}
class B extends A {
get m() { return () => 1; }
}

View File

@ -0,0 +1,15 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts ===
class A {
>A : Symbol(A, Decl(accessorsOverrideMethod.ts, 0, 0))
m() { }
>m : Symbol(A.m, Decl(accessorsOverrideMethod.ts, 0, 9))
}
class B extends A {
>B : Symbol(B, Decl(accessorsOverrideMethod.ts, 2, 1))
>A : Symbol(A, Decl(accessorsOverrideMethod.ts, 0, 0))
get m() { return () => 1 }
>m : Symbol(B.m, Decl(accessorsOverrideMethod.ts, 3, 19))
}

View File

@ -0,0 +1,17 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideMethod.ts ===
class A {
>A : A
m() { }
>m : () => void
}
class B extends A {
>B : B
>A : A
get m() { return () => 1 }
>m : () => number
>() => 1 : () => number
>1 : 1
}

View File

@ -0,0 +1,24 @@
tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts(5,9): error TS2611: Class 'A' defines instance member property 'p', but extended class 'B' defines it as instance member accessor.
tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts(12,9): error TS2611: Class 'C' defines instance member property 'p', but extended class 'D' defines it as instance member accessor.
==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts (2 errors) ====
class A {
p = 'yep'
}
class B extends A {
get p() { return 'oh no' } // error
~
!!! error TS2611: Class 'A' defines instance member property 'p', but extended class 'B' defines it as instance member accessor.
}
class C {
p = 101
}
class D extends C {
_secret = 11
get p() { return this._secret } // error
~
!!! error TS2611: Class 'C' defines instance member property 'p', but extended class 'D' defines it as instance member accessor.
set p(value) { this._secret = value } // error
}

View File

@ -0,0 +1,32 @@
//// [accessorsOverrideProperty.ts]
class A {
p = 'yep'
}
class B extends A {
get p() { return 'oh no' } // error
}
class C {
p = 101
}
class D extends C {
_secret = 11
get p() { return this._secret } // error
set p(value) { this._secret = value } // error
}
//// [accessorsOverrideProperty.js]
class A {
p = 'yep';
}
class B extends A {
get p() { return 'oh no'; } // error
}
class C {
p = 101;
}
class D extends C {
_secret = 11;
get p() { return this._secret; } // error
set p(value) { this._secret = value; } // error
}

View File

@ -0,0 +1,42 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts ===
class A {
>A : Symbol(A, Decl(accessorsOverrideProperty.ts, 0, 0))
p = 'yep'
>p : Symbol(A.p, Decl(accessorsOverrideProperty.ts, 0, 9))
}
class B extends A {
>B : Symbol(B, Decl(accessorsOverrideProperty.ts, 2, 1))
>A : Symbol(A, Decl(accessorsOverrideProperty.ts, 0, 0))
get p() { return 'oh no' } // error
>p : Symbol(B.p, Decl(accessorsOverrideProperty.ts, 3, 19))
}
class C {
>C : Symbol(C, Decl(accessorsOverrideProperty.ts, 5, 1))
p = 101
>p : Symbol(C.p, Decl(accessorsOverrideProperty.ts, 6, 9))
}
class D extends C {
>D : Symbol(D, Decl(accessorsOverrideProperty.ts, 8, 1))
>C : Symbol(C, Decl(accessorsOverrideProperty.ts, 5, 1))
_secret = 11
>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19))
get p() { return this._secret } // error
>p : Symbol(D.p, Decl(accessorsOverrideProperty.ts, 10, 17), Decl(accessorsOverrideProperty.ts, 11, 35))
>this._secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19))
>this : Symbol(D, Decl(accessorsOverrideProperty.ts, 8, 1))
>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19))
set p(value) { this._secret = value } // error
>p : Symbol(D.p, Decl(accessorsOverrideProperty.ts, 10, 17), Decl(accessorsOverrideProperty.ts, 11, 35))
>value : Symbol(value, Decl(accessorsOverrideProperty.ts, 12, 10))
>this._secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19))
>this : Symbol(D, Decl(accessorsOverrideProperty.ts, 8, 1))
>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty.ts, 9, 19))
>value : Symbol(value, Decl(accessorsOverrideProperty.ts, 12, 10))
}

View File

@ -0,0 +1,47 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty.ts ===
class A {
>A : A
p = 'yep'
>p : string
>'yep' : "yep"
}
class B extends A {
>B : B
>A : A
get p() { return 'oh no' } // error
>p : string
>'oh no' : "oh no"
}
class C {
>C : C
p = 101
>p : number
>101 : 101
}
class D extends C {
>D : D
>C : C
_secret = 11
>_secret : number
>11 : 11
get p() { return this._secret } // error
>p : number
>this._secret : number
>this : this
>_secret : number
set p(value) { this._secret = value } // error
>p : number
>value : number
>this._secret = value : number
>this._secret : number
>this : this
>_secret : number
>value : number
}

View File

@ -0,0 +1,18 @@
tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts(6,7): error TS2611: Class 'Base' defines instance member property 'x', but extended class 'Derived' defines it as instance member accessor.
==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts (1 errors) ====
class Base {
x = 1;
}
class Derived extends Base {
get x() { return 2; } // should be an error
~
!!! error TS2611: Class 'Base' defines instance member property 'x', but extended class 'Derived' defines it as instance member accessor.
set x(value) { console.log(`x was set to ${value}`); }
}
const obj = new Derived(); // nothing printed
console.log(obj.x); // 1

View File

@ -0,0 +1,24 @@
//// [accessorsOverrideProperty2.ts]
class Base {
x = 1;
}
class Derived extends Base {
get x() { return 2; } // should be an error
set x(value) { console.log(`x was set to ${value}`); }
}
const obj = new Derived(); // nothing printed
console.log(obj.x); // 1
//// [accessorsOverrideProperty2.js]
class Base {
x = 1;
}
class Derived extends Base {
get x() { return 2; } // should be an error
set x(value) { console.log(`x was set to ${value}`); }
}
const obj = new Derived(); // nothing printed
console.log(obj.x); // 1

View File

@ -0,0 +1,36 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts ===
class Base {
>Base : Symbol(Base, Decl(accessorsOverrideProperty2.ts, 0, 0))
x = 1;
>x : Symbol(Base.x, Decl(accessorsOverrideProperty2.ts, 0, 12))
}
class Derived extends Base {
>Derived : Symbol(Derived, Decl(accessorsOverrideProperty2.ts, 2, 1))
>Base : Symbol(Base, Decl(accessorsOverrideProperty2.ts, 0, 0))
get x() { return 2; } // should be an error
>x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23))
set x(value) { console.log(`x was set to ${value}`); }
>x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23))
>value : Symbol(value, Decl(accessorsOverrideProperty2.ts, 6, 8))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>value : Symbol(value, Decl(accessorsOverrideProperty2.ts, 6, 8))
}
const obj = new Derived(); // nothing printed
>obj : Symbol(obj, Decl(accessorsOverrideProperty2.ts, 9, 5))
>Derived : Symbol(Derived, Decl(accessorsOverrideProperty2.ts, 2, 1))
console.log(obj.x); // 1
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>obj.x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23))
>obj : Symbol(obj, Decl(accessorsOverrideProperty2.ts, 9, 5))
>x : Symbol(Derived.x, Decl(accessorsOverrideProperty2.ts, 4, 28), Decl(accessorsOverrideProperty2.ts, 5, 23))

View File

@ -0,0 +1,42 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty2.ts ===
class Base {
>Base : Base
x = 1;
>x : number
>1 : 1
}
class Derived extends Base {
>Derived : Derived
>Base : Base
get x() { return 2; } // should be an error
>x : number
>2 : 2
set x(value) { console.log(`x was set to ${value}`); }
>x : number
>value : number
>console.log(`x was set to ${value}`) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>`x was set to ${value}` : string
>value : number
}
const obj = new Derived(); // nothing printed
>obj : Derived
>new Derived() : Derived
>Derived : typeof Derived
console.log(obj.x); // 1
>console.log(obj.x) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>obj.x : number
>obj : Derived
>x : number

View File

@ -0,0 +1,15 @@
tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts(6,9): error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor.
==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts (1 errors) ====
declare class Animal {
sound: string
}
class Lion extends Animal {
_sound = 'grrr'
get sound() { return this._sound } // error here
~~~~~
!!! error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor.
set sound(val) { this._sound = val }
}

View File

@ -0,0 +1,17 @@
//// [accessorsOverrideProperty3.ts]
declare class Animal {
sound: string
}
class Lion extends Animal {
_sound = 'grrr'
get sound() { return this._sound } // error here
set sound(val) { this._sound = val }
}
//// [accessorsOverrideProperty3.js]
class Lion extends Animal {
_sound = 'grrr';
get sound() { return this._sound; } // error here
set sound(val) { this._sound = val; }
}

View File

@ -0,0 +1,29 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts ===
declare class Animal {
>Animal : Symbol(Animal, Decl(accessorsOverrideProperty3.ts, 0, 0))
sound: string
>sound : Symbol(Animal.sound, Decl(accessorsOverrideProperty3.ts, 0, 22))
}
class Lion extends Animal {
>Lion : Symbol(Lion, Decl(accessorsOverrideProperty3.ts, 2, 1))
>Animal : Symbol(Animal, Decl(accessorsOverrideProperty3.ts, 0, 0))
_sound = 'grrr'
>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27))
get sound() { return this._sound } // error here
>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty3.ts, 4, 19), Decl(accessorsOverrideProperty3.ts, 5, 38))
>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27))
>this : Symbol(Lion, Decl(accessorsOverrideProperty3.ts, 2, 1))
>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27))
set sound(val) { this._sound = val }
>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty3.ts, 4, 19), Decl(accessorsOverrideProperty3.ts, 5, 38))
>val : Symbol(val, Decl(accessorsOverrideProperty3.ts, 6, 14))
>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27))
>this : Symbol(Lion, Decl(accessorsOverrideProperty3.ts, 2, 1))
>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty3.ts, 3, 27))
>val : Symbol(val, Decl(accessorsOverrideProperty3.ts, 6, 14))
}

View File

@ -0,0 +1,31 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty3.ts ===
declare class Animal {
>Animal : Animal
sound: string
>sound : string
}
class Lion extends Animal {
>Lion : Lion
>Animal : Animal
_sound = 'grrr'
>_sound : string
>'grrr' : "grrr"
get sound() { return this._sound } // error here
>sound : string
>this._sound : string
>this : this
>_sound : string
set sound(val) { this._sound = val }
>sound : string
>val : string
>this._sound = val : string
>this._sound : string
>this : this
>_sound : string
>val : string
}

View File

@ -0,0 +1,15 @@
tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts(6,9): error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor.
==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts (1 errors) ====
declare class Animal {
sound: string;
}
class Lion extends Animal {
_sound = 'roar'
get sound(): string { return this._sound }
~~~~~
!!! error TS2611: Class 'Animal' defines instance member property 'sound', but extended class 'Lion' defines it as instance member accessor.
set sound(val: string) { this._sound = val }
}

View File

@ -0,0 +1,17 @@
//// [accessorsOverrideProperty4.ts]
declare class Animal {
sound: string;
}
class Lion extends Animal {
_sound = 'roar'
get sound(): string { return this._sound }
set sound(val: string) { this._sound = val }
}
//// [accessorsOverrideProperty4.js]
class Lion extends Animal {
_sound = 'roar';
get sound() { return this._sound; }
set sound(val) { this._sound = val; }
}

View File

@ -0,0 +1,29 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts ===
declare class Animal {
>Animal : Symbol(Animal, Decl(accessorsOverrideProperty4.ts, 0, 0))
sound: string;
>sound : Symbol(Animal.sound, Decl(accessorsOverrideProperty4.ts, 0, 22))
}
class Lion extends Animal {
>Lion : Symbol(Lion, Decl(accessorsOverrideProperty4.ts, 2, 1))
>Animal : Symbol(Animal, Decl(accessorsOverrideProperty4.ts, 0, 0))
_sound = 'roar'
>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27))
get sound(): string { return this._sound }
>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty4.ts, 4, 19), Decl(accessorsOverrideProperty4.ts, 5, 46))
>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27))
>this : Symbol(Lion, Decl(accessorsOverrideProperty4.ts, 2, 1))
>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27))
set sound(val: string) { this._sound = val }
>sound : Symbol(Lion.sound, Decl(accessorsOverrideProperty4.ts, 4, 19), Decl(accessorsOverrideProperty4.ts, 5, 46))
>val : Symbol(val, Decl(accessorsOverrideProperty4.ts, 6, 14))
>this._sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27))
>this : Symbol(Lion, Decl(accessorsOverrideProperty4.ts, 2, 1))
>_sound : Symbol(Lion._sound, Decl(accessorsOverrideProperty4.ts, 3, 27))
>val : Symbol(val, Decl(accessorsOverrideProperty4.ts, 6, 14))
}

View File

@ -0,0 +1,31 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty4.ts ===
declare class Animal {
>Animal : Animal
sound: string;
>sound : string
}
class Lion extends Animal {
>Lion : Lion
>Animal : Animal
_sound = 'roar'
>_sound : string
>'roar' : "roar"
get sound(): string { return this._sound }
>sound : string
>this._sound : string
>this : this
>_sound : string
set sound(val: string) { this._sound = val }
>sound : string
>val : string
>this._sound = val : string
>this._sound : string
>this : this
>_sound : string
>val : string
}

View File

@ -0,0 +1,19 @@
//// [accessorsOverrideProperty5.ts]
interface I {
p: number
}
interface B extends I { }
class B { }
class C extends B {
get p() { return 1 }
set p(value) { }
}
//// [accessorsOverrideProperty5.js]
class B {
}
class C extends B {
get p() { return 1; }
set p(value) { }
}

View File

@ -0,0 +1,26 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts ===
interface I {
>I : Symbol(I, Decl(accessorsOverrideProperty5.ts, 0, 0))
p: number
>p : Symbol(I.p, Decl(accessorsOverrideProperty5.ts, 0, 13))
}
interface B extends I { }
>B : Symbol(B, Decl(accessorsOverrideProperty5.ts, 2, 1), Decl(accessorsOverrideProperty5.ts, 3, 25))
>I : Symbol(I, Decl(accessorsOverrideProperty5.ts, 0, 0))
class B { }
>B : Symbol(B, Decl(accessorsOverrideProperty5.ts, 2, 1), Decl(accessorsOverrideProperty5.ts, 3, 25))
class C extends B {
>C : Symbol(C, Decl(accessorsOverrideProperty5.ts, 4, 11))
>B : Symbol(B, Decl(accessorsOverrideProperty5.ts, 2, 1), Decl(accessorsOverrideProperty5.ts, 3, 25))
get p() { return 1 }
>p : Symbol(C.p, Decl(accessorsOverrideProperty5.ts, 5, 19), Decl(accessorsOverrideProperty5.ts, 6, 24))
set p(value) { }
>p : Symbol(C.p, Decl(accessorsOverrideProperty5.ts, 5, 19), Decl(accessorsOverrideProperty5.ts, 6, 24))
>value : Symbol(value, Decl(accessorsOverrideProperty5.ts, 7, 10))
}

View File

@ -0,0 +1,22 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty5.ts ===
interface I {
p: number
>p : number
}
interface B extends I { }
class B { }
>B : B
class C extends B {
>C : C
>B : B
get p() { return 1 }
>p : number
>1 : 1
set p(value) { }
>p : number
>value : number
}

View File

@ -0,0 +1,39 @@
//// [accessorsOverrideProperty6.ts]
class A {
p = 'yep'
}
class B extends A {
get p() { return 'oh no' } // error
}
class C {
p = 101
}
class D extends C {
_secret = 11
get p() { return this._secret } // error
set p(value) { this._secret = value } // error
}
//// [accessorsOverrideProperty6.js]
class A {
constructor() {
this.p = 'yep';
}
}
class B extends A {
get p() { return 'oh no'; } // error
}
class C {
constructor() {
this.p = 101;
}
}
class D extends C {
constructor() {
super(...arguments);
this._secret = 11;
}
get p() { return this._secret; } // error
set p(value) { this._secret = value; } // error
}

View File

@ -0,0 +1,42 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty6.ts ===
class A {
>A : Symbol(A, Decl(accessorsOverrideProperty6.ts, 0, 0))
p = 'yep'
>p : Symbol(A.p, Decl(accessorsOverrideProperty6.ts, 0, 9))
}
class B extends A {
>B : Symbol(B, Decl(accessorsOverrideProperty6.ts, 2, 1))
>A : Symbol(A, Decl(accessorsOverrideProperty6.ts, 0, 0))
get p() { return 'oh no' } // error
>p : Symbol(B.p, Decl(accessorsOverrideProperty6.ts, 3, 19))
}
class C {
>C : Symbol(C, Decl(accessorsOverrideProperty6.ts, 5, 1))
p = 101
>p : Symbol(C.p, Decl(accessorsOverrideProperty6.ts, 6, 9))
}
class D extends C {
>D : Symbol(D, Decl(accessorsOverrideProperty6.ts, 8, 1))
>C : Symbol(C, Decl(accessorsOverrideProperty6.ts, 5, 1))
_secret = 11
>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty6.ts, 9, 19))
get p() { return this._secret } // error
>p : Symbol(D.p, Decl(accessorsOverrideProperty6.ts, 10, 17), Decl(accessorsOverrideProperty6.ts, 11, 35))
>this._secret : Symbol(D._secret, Decl(accessorsOverrideProperty6.ts, 9, 19))
>this : Symbol(D, Decl(accessorsOverrideProperty6.ts, 8, 1))
>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty6.ts, 9, 19))
set p(value) { this._secret = value } // error
>p : Symbol(D.p, Decl(accessorsOverrideProperty6.ts, 10, 17), Decl(accessorsOverrideProperty6.ts, 11, 35))
>value : Symbol(value, Decl(accessorsOverrideProperty6.ts, 12, 10))
>this._secret : Symbol(D._secret, Decl(accessorsOverrideProperty6.ts, 9, 19))
>this : Symbol(D, Decl(accessorsOverrideProperty6.ts, 8, 1))
>_secret : Symbol(D._secret, Decl(accessorsOverrideProperty6.ts, 9, 19))
>value : Symbol(value, Decl(accessorsOverrideProperty6.ts, 12, 10))
}

View File

@ -0,0 +1,47 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty6.ts ===
class A {
>A : A
p = 'yep'
>p : string
>'yep' : "yep"
}
class B extends A {
>B : B
>A : A
get p() { return 'oh no' } // error
>p : string
>'oh no' : "oh no"
}
class C {
>C : C
p = 101
>p : number
>101 : 101
}
class D extends C {
>D : D
>C : C
_secret = 11
>_secret : number
>11 : 11
get p() { return this._secret } // error
>p : number
>this._secret : number
>this : this
>_secret : number
set p(value) { this._secret = value } // error
>p : number
>value : number
>this._secret = value : number
>this._secret : number
>this : this
>_secret : number
>value : number
}

View File

@ -0,0 +1,13 @@
tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty7.ts(5,9): error TS2611: Class 'A' defines instance member property 'p', but extended class 'B' defines it as instance member accessor.
==== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty7.ts (1 errors) ====
abstract class A {
abstract p = 'yep'
}
class B extends A {
get p() { return 'oh no' } // error
~
!!! error TS2611: Class 'A' defines instance member property 'p', but extended class 'B' defines it as instance member accessor.
}

View File

@ -0,0 +1,47 @@
//// [accessorsOverrideProperty7.ts]
abstract class A {
abstract p = 'yep'
}
class B extends A {
get p() { return 'oh no' } // error
}
//// [accessorsOverrideProperty7.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var A = /** @class */ (function () {
function A() {
Object.defineProperty(this, "p", {
enumerable: true,
configurable: true,
writable: true,
value: 'yep'
});
}
return A;
}());
var B = /** @class */ (function (_super) {
__extends(B, _super);
function B() {
return _super !== null && _super.apply(this, arguments) || this;
}
Object.defineProperty(B.prototype, "p", {
get: function () { return 'oh no'; } // error
,
enumerable: true,
configurable: true
});
return B;
}(A));

View File

@ -0,0 +1,15 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty7.ts ===
abstract class A {
>A : Symbol(A, Decl(accessorsOverrideProperty7.ts, 0, 0))
abstract p = 'yep'
>p : Symbol(A.p, Decl(accessorsOverrideProperty7.ts, 0, 18))
}
class B extends A {
>B : Symbol(B, Decl(accessorsOverrideProperty7.ts, 2, 1))
>A : Symbol(A, Decl(accessorsOverrideProperty7.ts, 0, 0))
get p() { return 'oh no' } // error
>p : Symbol(B.p, Decl(accessorsOverrideProperty7.ts, 3, 19))
}

View File

@ -0,0 +1,17 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty7.ts ===
abstract class A {
>A : A
abstract p = 'yep'
>p : string
>'yep' : "yep"
}
class B extends A {
>B : B
>A : A
get p() { return 'oh no' } // error
>p : string
>'oh no' : "oh no"
}

View File

@ -2637,6 +2637,7 @@ declare namespace ts {
/** Paths used to compute primary types search locations */
typeRoots?: string[];
esModuleInterop?: boolean;
useDefineForClassFields?: boolean;
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
}
export interface TypeAcquisition {
@ -3585,7 +3586,7 @@ declare namespace ts {
function isUnparsedTextLike(node: Node): node is UnparsedTextLike;
function isUnparsedNode(node: Node): node is UnparsedNode;
function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression;
function isJSDocAllType(node: JSDocAllType): node is JSDocAllType;
function isJSDocAllType(node: Node): node is JSDocAllType;
function isJSDocUnknownType(node: Node): node is JSDocUnknownType;
function isJSDocNullableType(node: Node): node is JSDocNullableType;
function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType;
@ -5298,6 +5299,11 @@ declare namespace ts {
Block = 1,
Smart = 2
}
enum SemicolonPreference {
Ignore = "ignore",
Insert = "insert",
Remove = "remove"
}
interface EditorOptions {
BaseIndentSize?: number;
IndentSize: number;
@ -5350,6 +5356,7 @@ declare namespace ts {
readonly placeOpenBraceOnNewLineForControlBlocks?: boolean;
readonly insertSpaceBeforeTypeAnnotation?: boolean;
readonly indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean;
readonly semicolons?: SemicolonPreference;
}
function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatCodeSettings;
interface DefinitionInfo extends DocumentSpan {
@ -8197,6 +8204,11 @@ declare namespace ts.server.protocol {
Block = "Block",
Smart = "Smart"
}
enum SemicolonPreference {
Ignore = "ignore",
Insert = "insert",
Remove = "remove"
}
interface EditorSettings {
baseIndentSize?: number;
indentSize?: number;
@ -8222,6 +8234,7 @@ declare namespace ts.server.protocol {
placeOpenBraceOnNewLineForFunctions?: boolean;
placeOpenBraceOnNewLineForControlBlocks?: boolean;
insertSpaceBeforeTypeAnnotation?: boolean;
semicolons?: SemicolonPreference;
}
interface UserPreferences {
readonly disableSuggestions?: boolean;
@ -8305,6 +8318,7 @@ declare namespace ts.server.protocol {
strictNullChecks?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
useDefineForClassFields?: boolean;
target?: ScriptTarget | ts.ScriptTarget;
traceResolution?: boolean;
resolveJsonModule?: boolean;

View File

@ -2637,6 +2637,7 @@ declare namespace ts {
/** Paths used to compute primary types search locations */
typeRoots?: string[];
esModuleInterop?: boolean;
useDefineForClassFields?: boolean;
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
}
export interface TypeAcquisition {
@ -3585,7 +3586,7 @@ declare namespace ts {
function isUnparsedTextLike(node: Node): node is UnparsedTextLike;
function isUnparsedNode(node: Node): node is UnparsedNode;
function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression;
function isJSDocAllType(node: JSDocAllType): node is JSDocAllType;
function isJSDocAllType(node: Node): node is JSDocAllType;
function isJSDocUnknownType(node: Node): node is JSDocUnknownType;
function isJSDocNullableType(node: Node): node is JSDocNullableType;
function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType;
@ -5298,6 +5299,11 @@ declare namespace ts {
Block = 1,
Smart = 2
}
enum SemicolonPreference {
Ignore = "ignore",
Insert = "insert",
Remove = "remove"
}
interface EditorOptions {
BaseIndentSize?: number;
IndentSize: number;
@ -5350,6 +5356,7 @@ declare namespace ts {
readonly placeOpenBraceOnNewLineForControlBlocks?: boolean;
readonly insertSpaceBeforeTypeAnnotation?: boolean;
readonly indentMultiLineObjectLiteralBeginningOnBlankLine?: boolean;
readonly semicolons?: SemicolonPreference;
}
function getDefaultFormatCodeSettings(newLineCharacter?: string): FormatCodeSettings;
interface DefinitionInfo extends DocumentSpan {

View File

@ -10,7 +10,7 @@ namespace foo {
>1 : 1
}
export = foo;
>foo : typeof foo
>foo : typeof import("tests/cases/compiler/file1")
=== tests/cases/compiler/file2.ts ===
import x = require("./file1");

View File

@ -10,7 +10,7 @@ namespace foo {
>1 : 1
}
export = foo;
>foo : foo
>foo : import("tests/cases/compiler/file1")
=== tests/cases/compiler/file2.ts ===
import x = require("./file1");

View File

@ -18,7 +18,7 @@ declare module "express" {
function e(): e.Express;
>e : Symbol(e, Decl(express.d.ts, 6, 26), Decl(express.d.ts, 7, 28), Decl(augmentation.ts, 1, 29))
>e : Symbol(e, Decl(express.d.ts, 6, 26), Decl(express.d.ts, 7, 28))
>Express : Symbol(Express, Decl(express.d.ts, 52, 9))
>Express : Symbol(e.Express, Decl(express.d.ts, 52, 9))
namespace e {
>e : Symbol(e, Decl(express.d.ts, 6, 26), Decl(express.d.ts, 7, 28), Decl(augmentation.ts, 1, 29))

View File

@ -13,7 +13,7 @@ namespace foo {
>a : any
}
export = foo;
>foo : foo
>foo : import("tests/cases/compiler/file1")
=== tests/cases/compiler/file2.ts ===
import x = require("./file1");

View File

@ -0,0 +1,25 @@
tests/cases/compiler/a.js(14,10): error TS2424: Class 'A' defines instance member function 'foo', but extended class 'B' defines it as instance member property.
==== tests/cases/compiler/a.js (1 errors) ====
// @ts-check
class A {
constructor() {
}
foo() {
return 4;
}
}
class B extends A {
constructor() {
super();
this.foo = () => 3;
~~~
!!! error TS2424: Class 'A' defines instance member function 'foo', but extended class 'B' defines it as instance member property.
}
}
const i = new B();
i.foo();

View File

@ -22,11 +22,11 @@ export = Foo;
/** @typedef {(foo: Foo) => string} FooFun */
module.exports = /** @type {FooFun} */(void 0);
>module.exports = /** @type {FooFun} */(void 0) : (foo: typeof Foo) => string
>module.exports : (foo: typeof Foo) => string
>module : { "tests/cases/compiler/something": (foo: typeof Foo) => string; }
>exports : (foo: typeof Foo) => string
>(void 0) : (foo: typeof Foo) => string
>module.exports = /** @type {FooFun} */(void 0) : (foo: typeof import("tests/cases/compiler/file")) => string
>module.exports : (foo: typeof import("tests/cases/compiler/file")) => string
>module : { "tests/cases/compiler/something": (foo: typeof import("tests/cases/compiler/file")) => string; }
>exports : (foo: typeof import("tests/cases/compiler/file")) => string
>(void 0) : (foo: typeof import("tests/cases/compiler/file")) => string
>void 0 : undefined
>0 : 0

View File

@ -1,12 +1,12 @@
tests/cases/compiler/classExpressionPropertyModifiers.ts(2,5): error TS1031: 'declare' modifier cannot appear on a class element.
tests/cases/compiler/classExpressionPropertyModifiers.ts(2,36): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/classExpressionPropertyModifiers.ts(3,5): error TS1031: 'export' modifier cannot appear on a class element.
==== tests/cases/compiler/classExpressionPropertyModifiers.ts (2 errors) ====
const a = class Cat {
declare [Symbol.toStringTag] = "uh";
~~~~~~~
!!! error TS1031: 'declare' modifier cannot appear on a class element.
~~~~
!!! error TS1039: Initializers are not allowed in ambient contexts.
export foo = 1;
~~~~~~
!!! error TS1031: 'export' modifier cannot appear on a class element.

View File

@ -218,13 +218,14 @@ declare class a {
constructor(s: string);
pgF(): void;
pv: any;
d: number;
static readonly p2: {
get d(): number;
set d(a: number);
static get p2(): {
x: number;
y: number;
};
private static d2;
private static readonly p3;
private static get p3();
private pv3;
private foo;
}

View File

@ -486,15 +486,17 @@ declare class c1 {
/** sum with property*/
p2(/** number to add*/ b: number): number;
/** getter property*/
get p3(): number;
/** setter property*/
p3: number;
set p3(/** this is value*/ value: number);
/** pp1 is property of c1*/
private pp1;
/** sum with property*/
private pp2;
/** getter property*/
private get pp3();
/** setter property*/
private pp3;
private set pp3(value);
/** Constructor method*/
constructor();
/** s1 is static property of c1*/
@ -502,49 +504,59 @@ declare class c1 {
/** static sum with property*/
static s2(/** number to add*/ b: number): number;
/** static getter property*/
static get s3(): number;
/** setter property*/
static s3: number;
static set s3(/** this is value*/ value: number);
nc_p1: number;
nc_p2(b: number): number;
nc_p3: number;
get nc_p3(): number;
set nc_p3(value: number);
private nc_pp1;
private nc_pp2;
private nc_pp3;
private get nc_pp3();
private set nc_pp3(value);
static nc_s1: number;
static nc_s2(b: number): number;
static nc_s3: number;
static get nc_s3(): number;
static set nc_s3(value: number);
a_p1: number;
a_p2(b: number): number;
a_p3: number;
get a_p3(): number;
set a_p3(value: number);
private a_pp1;
private a_pp2;
private a_pp3;
private get a_pp3();
private set a_pp3(value);
static a_s1: number;
static a_s2(b: number): number;
static a_s3: number;
static get a_s3(): number;
static set a_s3(value: number);
/** p1 is property of c1 */
b_p1: number;
/** sum with property */
b_p2(b: number): number;
/** getter property */
get b_p3(): number;
/** setter property */
b_p3: number;
set b_p3(value: number);
/** pp1 is property of c1 */
private b_pp1;
/** sum with property */
private b_pp2;
/** getter property */
private get b_pp3();
/** setter property */
private b_pp3;
private set b_pp3(value);
/** s1 is static property of c1 */
static b_s1: number;
/** static sum with property */
static b_s2(b: number): number;
/** static getter property
*/
static get b_s3(): number;
/** setter property
*/
static b_s3: number;
static set b_s3(value: number);
}
declare var i1: c1;
declare var i1_p: number;
@ -567,11 +579,11 @@ declare var i1_c: typeof c1;
declare class cProperties {
private val;
/** getter only property*/
readonly p1: number;
readonly nc_p1: number;
get p1(): number;
get nc_p1(): number;
/**setter only property*/
p2: number;
nc_p2: number;
set p2(value: number);
set nc_p2(value: number);
x: number;
private y;
}

View File

@ -323,19 +323,19 @@ declare class c2 {
/** c2 c2_f1*/
c2_f1(): void;
/** c2 c2_prop*/
readonly c2_prop: number;
get c2_prop(): number;
c2_nc_p1: number;
c2_nc_f1(): void;
readonly c2_nc_prop: number;
get c2_nc_prop(): number;
/** c2 p1*/
p1: number;
/** c2 f1*/
f1(): void;
/** c2 prop*/
readonly prop: number;
get prop(): number;
nc_p1: number;
nc_f1(): void;
readonly nc_prop: number;
get nc_prop(): number;
/** c2 constructor*/
constructor(a: number);
}
@ -346,10 +346,10 @@ declare class c3 extends c2 {
/** c3 f1*/
f1(): void;
/** c3 prop*/
readonly prop: number;
get prop(): number;
nc_p1: number;
nc_f1(): void;
readonly nc_prop: number;
get nc_prop(): number;
}
declare var c2_i: c2;
declare var c3_i: c3;

View File

@ -144,7 +144,8 @@ declare class c {
constructor();
b: number;
myFoo(): number;
prop1: number;
get prop1(): number;
set prop1(val: number);
foo1(a: number): string;
foo1(b: string): string;
}

View File

@ -160,8 +160,9 @@ declare class c {
/** function comment */
myFoo(): number;
/** getter comment*/
get prop1(): number;
/** setter comment*/
prop1: number;
set prop1(val: number);
/** overload signature1*/
foo1(a: number): string;
/** Overload signature 2*/

View File

@ -9,16 +9,16 @@ declare var module: any, exports: any;
=== tests/cases/conformance/salsa/index.js ===
const A = require("./other");
>A : typeof A
>require("./other") : typeof A
>A : typeof import("tests/cases/conformance/salsa/other")
>require("./other") : typeof import("tests/cases/conformance/salsa/other")
>require : (id: string) => any
>"./other" : "./other"
const a = new A().id;
>a : number
>new A().id : number
>new A() : A
>A : typeof A
>new A() : import("tests/cases/conformance/salsa/other")
>A : typeof import("tests/cases/conformance/salsa/other")
>id : number
const B = function() { this.id = 1; }

View File

@ -273,35 +273,47 @@ var c2 = /** @class */ (function () {
/** This is comment for c1*/
export declare class c1 {
/** getter property*/
get p3(): number;
/** setter property*/
p3: number;
set p3(/** this is value*/ value: number);
/** private getter property*/
private get pp3();
/** private setter property*/
private pp3;
private set pp3(value);
/** static getter property*/
static get s3(): number;
/** setter property*/
static s3: number;
nc_p3: number;
private nc_pp3;
static nc_s3: string;
readonly onlyGetter: number;
onlySetter: number;
static set s3(/** this is value*/ value: number);
get nc_p3(): number;
set nc_p3(value: number);
private get nc_pp3();
private set nc_pp3(value);
static get nc_s3(): string;
static set nc_s3(value: string);
get onlyGetter(): number;
set onlySetter(value: number);
}
//// [declFileAccessors_1.d.ts]
/** This is comment for c2 - the global class*/
declare class c2 {
/** getter property*/
get p3(): number;
/** setter property*/
p3: number;
set p3(/** this is value*/ value: number);
/** private getter property*/
private get pp3();
/** private setter property*/
private pp3;
private set pp3(value);
/** static getter property*/
static get s3(): number;
/** setter property*/
static s3: number;
nc_p3: number;
private nc_pp3;
static nc_s3: string;
readonly onlyGetter: number;
onlySetter: number;
static set s3(/** this is value*/ value: number);
get nc_p3(): number;
set nc_p3(value: number);
private get nc_pp3();
private set nc_pp3(value);
static get nc_s3(): string;
static set nc_s3(value: string);
get onlyGetter(): number;
set onlySetter(value: number);
}

View File

@ -51,8 +51,8 @@ declare class C {
static y: number;
private static a;
static b(): void;
private static readonly c;
static readonly d: number;
private static e;
static f: any;
private static get c();
static get d(): number;
private static set e(value);
static set f(v: any);
}

View File

@ -271,21 +271,27 @@ declare module m {
}
}
export class c {
readonly foo1: private1;
readonly foo2: private1;
foo3: private1;
foo4: private1;
foo5: private1;
readonly foo11: public1;
readonly foo12: public1;
foo13: public1;
foo14: public1;
foo15: public1;
readonly foo111: m2.public2;
readonly foo112: m2.public2;
foo113: m2.public2;
foo114: m2.public2;
foo115: m2.public2;
get foo1(): private1;
get foo2(): private1;
set foo3(param: private1);
get foo4(): private1;
set foo4(param: private1);
get foo5(): private1;
set foo5(param: private1);
get foo11(): public1;
get foo12(): public1;
set foo13(param: public1);
get foo14(): public1;
set foo14(param: public1);
get foo15(): public1;
set foo15(param: public1);
get foo111(): m2.public2;
get foo112(): m2.public2;
set foo113(param: m2.public2);
get foo114(): m2.public2;
set foo114(param: m2.public2);
get foo115(): m2.public2;
set foo115(param: m2.public2);
}
export {};
}

View File

@ -103,10 +103,10 @@ export declare class C2 {
bar(): (t: typeof C2) => void;
}
export declare class C3 {
readonly C3: number;
get C3(): number;
bar(): (t: typeof C3) => void;
}
export declare class C4 {
C4: any;
set C4(v: any);
bar(): (t: typeof C4) => void;
}

View File

@ -167,7 +167,7 @@ export declare module M.P {
var a: typeof M.f;
var b: typeof M.C;
var c: typeof M.N;
var g: typeof M.c.g;
var g: typeof M.N.g;
var d: typeof M.d;
}
export declare module M.Q {

View File

@ -138,11 +138,12 @@ var C4 = /** @class */ (function () {
declare class C1 {
protected x: number;
protected f(): number;
protected accessor: number;
protected set accessor(a: number);
protected get accessor(): number;
protected static sx: number;
protected static sf(): number;
protected static staticSetter: number;
protected static readonly staticGetter: number;
protected static set staticSetter(a: number);
protected static get staticGetter(): number;
}
declare class C2 extends C1 {
protected f(): number;
@ -153,7 +154,7 @@ declare class C3 extends C2 {
static sx: number;
f(): number;
static sf(): number;
static readonly staticGetter: number;
static get staticGetter(): number;
}
declare class C4 {
protected a: number;

View File

@ -0,0 +1,22 @@
tests/cases/compiler/input.ts(1,1): error TS2309: An export assignment cannot be used in a module with other exported elements.
tests/cases/compiler/input.ts(6,14): error TS2323: Cannot redeclare exported variable 'Sub'.
==== tests/cases/compiler/input.ts (2 errors) ====
export = exports;
~~~~~~~~~~~~~~~~~
!!! error TS2309: An export assignment cannot be used in a module with other exported elements.
declare class exports {
constructor(p: number);
t: number;
}
export class Sub {
~~~
!!! error TS2323: Cannot redeclare exported variable 'Sub'.
instance!: {
t: number;
};
}
declare namespace exports {
export { Sub };
}

View File

@ -0,0 +1,23 @@
//// [input.ts]
export = exports;
declare class exports {
constructor(p: number);
t: number;
}
export class Sub {
instance!: {
t: number;
};
}
declare namespace exports {
export { Sub };
}
//// [input.js]
"use strict";
var Sub = /** @class */ (function () {
function Sub() {
}
return Sub;
}());
module.exports = exports;

View File

@ -0,0 +1,30 @@
=== tests/cases/compiler/input.ts ===
export = exports;
>exports : Symbol(exports, Decl(input.ts, 0, 17), Decl(input.ts, 9, 1))
declare class exports {
>exports : Symbol(exports, Decl(input.ts, 0, 17), Decl(input.ts, 9, 1))
constructor(p: number);
>p : Symbol(p, Decl(input.ts, 2, 16))
t: number;
>t : Symbol(exports.t, Decl(input.ts, 2, 27))
}
export class Sub {
>Sub : Symbol(Sub, Decl(input.ts, 4, 1), Decl(input.ts, 4, 1))
instance!: {
>instance : Symbol(Sub.instance, Decl(input.ts, 5, 18))
t: number;
>t : Symbol(t, Decl(input.ts, 6, 16))
};
}
declare namespace exports {
>exports : Symbol(exports, Decl(input.ts, 0, 17), Decl(input.ts, 9, 1))
export { Sub };
>Sub : Symbol(exports.Sub, Decl(input.ts, 11, 12))
}

View File

@ -0,0 +1,30 @@
=== tests/cases/compiler/input.ts ===
export = exports;
>exports : import("tests/cases/compiler/input")
declare class exports {
>exports : exports
constructor(p: number);
>p : number
t: number;
>t : number
}
export class Sub {
>Sub : Sub
instance!: {
>instance : { t: number; }
t: number;
>t : number
};
}
declare namespace exports {
>exports : typeof exports
export { Sub };
>Sub : typeof import("tests/cases/compiler/input").Sub
}

Some files were not shown because too many files have changed in this diff Show More