mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 20:14:01 -06:00
Merge branch 'small_ts' of https://github.com/orta/TypeScript into small_ts
This commit is contained in:
commit
4c4a683d03
2
.gitignore
vendored
2
.gitignore
vendored
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
@ -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",
|
||||
|
||||
@ -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 { }
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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*/
|
||||
|
||||
@ -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>;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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.");
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
34
src/services/codefixes/addMissingDeclareProperty.ts
Normal file
34
src/services/codefixes/addMissingDeclareProperty.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -99,4 +99,4 @@ namespace ts.formatting {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
) {
|
||||
// Can’t 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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 parser’s `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++;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
286
src/testRunner/unittests/tsbuild/javascriptProjectEmit.ts
Normal file
286
src/testRunner/unittests/tsbuild/javascriptProjectEmit.ts
Normal 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"]
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -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", () => {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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])
|
||||
|
||||
13
tests/baselines/reference/accessorsOverrideMethod.errors.txt
Normal file
13
tests/baselines/reference/accessorsOverrideMethod.errors.txt
Normal 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.
|
||||
}
|
||||
|
||||
16
tests/baselines/reference/accessorsOverrideMethod.js
Normal file
16
tests/baselines/reference/accessorsOverrideMethod.js
Normal 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; }
|
||||
}
|
||||
15
tests/baselines/reference/accessorsOverrideMethod.symbols
Normal file
15
tests/baselines/reference/accessorsOverrideMethod.symbols
Normal 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))
|
||||
}
|
||||
|
||||
17
tests/baselines/reference/accessorsOverrideMethod.types
Normal file
17
tests/baselines/reference/accessorsOverrideMethod.types
Normal 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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
32
tests/baselines/reference/accessorsOverrideProperty.js
Normal file
32
tests/baselines/reference/accessorsOverrideProperty.js
Normal 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
|
||||
}
|
||||
42
tests/baselines/reference/accessorsOverrideProperty.symbols
Normal file
42
tests/baselines/reference/accessorsOverrideProperty.symbols
Normal 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))
|
||||
}
|
||||
|
||||
47
tests/baselines/reference/accessorsOverrideProperty.types
Normal file
47
tests/baselines/reference/accessorsOverrideProperty.types
Normal 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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
24
tests/baselines/reference/accessorsOverrideProperty2.js
Normal file
24
tests/baselines/reference/accessorsOverrideProperty2.js
Normal 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
|
||||
36
tests/baselines/reference/accessorsOverrideProperty2.symbols
Normal file
36
tests/baselines/reference/accessorsOverrideProperty2.symbols
Normal 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))
|
||||
|
||||
42
tests/baselines/reference/accessorsOverrideProperty2.types
Normal file
42
tests/baselines/reference/accessorsOverrideProperty2.types
Normal 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
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
|
||||
17
tests/baselines/reference/accessorsOverrideProperty3.js
Normal file
17
tests/baselines/reference/accessorsOverrideProperty3.js
Normal 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; }
|
||||
}
|
||||
29
tests/baselines/reference/accessorsOverrideProperty3.symbols
Normal file
29
tests/baselines/reference/accessorsOverrideProperty3.symbols
Normal 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))
|
||||
}
|
||||
|
||||
31
tests/baselines/reference/accessorsOverrideProperty3.types
Normal file
31
tests/baselines/reference/accessorsOverrideProperty3.types
Normal 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
|
||||
}
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
|
||||
17
tests/baselines/reference/accessorsOverrideProperty4.js
Normal file
17
tests/baselines/reference/accessorsOverrideProperty4.js
Normal 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; }
|
||||
}
|
||||
29
tests/baselines/reference/accessorsOverrideProperty4.symbols
Normal file
29
tests/baselines/reference/accessorsOverrideProperty4.symbols
Normal 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))
|
||||
}
|
||||
|
||||
31
tests/baselines/reference/accessorsOverrideProperty4.types
Normal file
31
tests/baselines/reference/accessorsOverrideProperty4.types
Normal 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
|
||||
}
|
||||
|
||||
19
tests/baselines/reference/accessorsOverrideProperty5.js
Normal file
19
tests/baselines/reference/accessorsOverrideProperty5.js
Normal 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) { }
|
||||
}
|
||||
26
tests/baselines/reference/accessorsOverrideProperty5.symbols
Normal file
26
tests/baselines/reference/accessorsOverrideProperty5.symbols
Normal 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))
|
||||
}
|
||||
|
||||
22
tests/baselines/reference/accessorsOverrideProperty5.types
Normal file
22
tests/baselines/reference/accessorsOverrideProperty5.types
Normal 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
|
||||
}
|
||||
|
||||
39
tests/baselines/reference/accessorsOverrideProperty6.js
Normal file
39
tests/baselines/reference/accessorsOverrideProperty6.js
Normal 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
|
||||
}
|
||||
42
tests/baselines/reference/accessorsOverrideProperty6.symbols
Normal file
42
tests/baselines/reference/accessorsOverrideProperty6.symbols
Normal 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))
|
||||
}
|
||||
|
||||
47
tests/baselines/reference/accessorsOverrideProperty6.types
Normal file
47
tests/baselines/reference/accessorsOverrideProperty6.types
Normal 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
|
||||
}
|
||||
|
||||
@ -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.
|
||||
}
|
||||
|
||||
47
tests/baselines/reference/accessorsOverrideProperty7.js
Normal file
47
tests/baselines/reference/accessorsOverrideProperty7.js
Normal 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));
|
||||
15
tests/baselines/reference/accessorsOverrideProperty7.symbols
Normal file
15
tests/baselines/reference/accessorsOverrideProperty7.symbols
Normal 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))
|
||||
}
|
||||
|
||||
17
tests/baselines/reference/accessorsOverrideProperty7.types
Normal file
17
tests/baselines/reference/accessorsOverrideProperty7.types
Normal 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"
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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();
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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*/
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 {};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 };
|
||||
}
|
||||
@ -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;
|
||||
@ -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))
|
||||
}
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user