Merge branch 'master' into jsdoc-values-as-namespaces

This commit is contained in:
Nathan Shively-Sanders
2017-11-21 10:26:08 -08:00
56 changed files with 39674 additions and 600 deletions
+9 -7
View File
@@ -517,16 +517,15 @@ namespace ts {
const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !hasModifier(node, ModifierFlags.Async) && !!getImmediatelyInvokedFunctionExpression(node);
// A non-async IIFE is considered part of the containing control flow. Return statements behave
// similarly to break statements that exit to a label just past the statement body.
if (isIIFE) {
currentReturnTarget = createBranchLabel();
}
else {
if (!isIIFE) {
currentFlow = { flags: FlowFlags.Start };
if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethod)) {
(<FlowStart>currentFlow).container = <FunctionExpression | ArrowFunction | MethodDeclaration>node;
}
currentReturnTarget = undefined;
}
// We create a return control flow graph for IIFEs and constructors. For constructors
// we use the return control flow graph in strict property intialization checks.
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
currentBreakTarget = undefined;
currentContinueTarget = undefined;
activeLabels = undefined;
@@ -541,11 +540,14 @@ namespace ts {
if (node.kind === SyntaxKind.SourceFile) {
node.flags |= emitFlags;
}
if (isIIFE) {
if (currentReturnTarget) {
addAntecedent(currentReturnTarget, currentFlow);
currentFlow = finishFlowLabel(currentReturnTarget);
if (node.kind === SyntaxKind.Constructor) {
(<ConstructorDeclaration>node).returnFlowNode = currentFlow;
}
}
else {
if (!isIIFE) {
currentFlow = saveCurrentFlow;
}
currentBreakTarget = saveBreakTarget;
+101 -47
View File
@@ -69,6 +69,7 @@ namespace ts {
const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions);
const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization");
const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis");
@@ -8879,6 +8880,7 @@ namespace ts {
// An object type S is considered to be derived from an object type T if
// S is a union type and every constituent of S is derived from T,
// T is a union type and S is derived from at least one constituent of T, or
// S is a type variable with a base constraint that is derived from T,
// T is one of the global types Object and Function and S is a subtype of T, or
// T occurs directly or indirectly in an 'extends' clause of S.
// Note that this check ignores type parameters and only considers the
@@ -8886,6 +8888,7 @@ namespace ts {
function isTypeDerivedFrom(source: Type, target: Type): boolean {
return source.flags & TypeFlags.Union ? every((<UnionType>source).types, t => isTypeDerivedFrom(t, target)) :
target.flags & TypeFlags.Union ? some((<UnionType>target).types, t => isTypeDerivedFrom(source, t)) :
source.flags & TypeFlags.TypeVariable ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) :
target === globalObjectType || target === globalFunctionType ? isTypeSubtypeOf(source, target) :
hasBaseType(source, getTargetType(target));
}
@@ -12294,7 +12297,7 @@ namespace ts {
// on empty arrays are possible without implicit any errors and new element types can be inferred without
// type mismatch errors.
const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType);
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
if (reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
return declaredType;
}
return resultType;
@@ -13131,8 +13134,10 @@ namespace ts {
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
// declaration container are the same).
const assumeInitialized = isParameter || isAlias || isOuterVariable ||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 ||
isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
node.parent.kind === SyntaxKind.NonNullExpression ||
declaration.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>declaration).exclamationToken ||
declaration.flags & NodeFlags.Ambient;
const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) :
type === autoType || type === autoArrayType ? undefinedType :
@@ -15572,63 +15577,68 @@ namespace ts {
}
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
const type = checkNonNullExpression(left);
if (isTypeAny(type) || type === silentNeverType) {
return type;
}
const apparentType = getApparentType(getWidenedType(type));
if (apparentType === unknownType || (type.flags & TypeFlags.TypeParameter && isTypeAny(apparentType))) {
// handle cases when type is Type parameter with invalid or any constraint
let propType: Type;
const leftType = checkNonNullExpression(left);
const apparentType = getApparentType(getWidenedType(leftType));
if (isTypeAny(apparentType) || apparentType === silentNeverType) {
return apparentType;
}
const assignmentKind = getAssignmentTargetKind(node);
const prop = getPropertyOfType(apparentType, right.escapedText);
if (!prop) {
const indexInfo = getIndexInfoOfType(apparentType, IndexKind.String);
if (indexInfo && indexInfo.type) {
if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) {
error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType));
if (!(indexInfo && indexInfo.type)) {
if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) {
reportNonexistentProperty(right, leftType.flags & TypeFlags.TypeParameter && (leftType as TypeParameter).isThisType ? apparentType : leftType);
}
return getFlowTypeOfPropertyAccess(node, /*prop*/ undefined, indexInfo.type, getAssignmentTargetKind(node));
}
if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) {
reportNonexistentProperty(right, type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType ? apparentType : type);
}
return unknownType;
}
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
getNodeLinks(node).resolvedSymbol = prop;
checkPropertyAccessibility(node, left, apparentType, prop);
const propType = getDeclaredOrApparentType(prop, node);
const assignmentKind = getAssignmentTargetKind(node);
if (assignmentKind) {
if (isReferenceToReadonlyEntity(<Expression>node, prop) || isReferenceThroughNamespaceImport(<Expression>node)) {
error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, idText(right));
return unknownType;
}
if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) {
error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType));
}
propType = indexInfo.type;
}
return getFlowTypeOfPropertyAccess(node, prop, propType, assignmentKind);
}
/**
* Only compute control flow type if this is a property access expression that isn't an
* assignment target, and the referenced property was declared as a variable, property,
* accessor, or optional method.
*/
function getFlowTypeOfPropertyAccess(node: PropertyAccessExpression | QualifiedName, prop: Symbol | undefined, type: Type, assignmentKind: AssignmentKind) {
else {
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
getNodeLinks(node).resolvedSymbol = prop;
checkPropertyAccessibility(node, left, apparentType, prop);
if (assignmentKind) {
if (isReferenceToReadonlyEntity(<Expression>node, prop) || isReferenceThroughNamespaceImport(<Expression>node)) {
error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, idText(right));
return unknownType;
}
}
propType = getDeclaredOrApparentType(prop, node);
}
// Only compute control flow type if this is a property access expression that isn't an
// assignment target, and the referenced property was declared as a variable, property,
// accessor, or optional method.
if (node.kind !== SyntaxKind.PropertyAccessExpression ||
assignmentKind === AssignmentKind.Definite ||
prop && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && !(prop.flags & SymbolFlags.Method && type.flags & TypeFlags.Union)) {
return type;
prop && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) {
return propType;
}
// If strict null checks and strict property initialization checks are enabled, if we have
// a this.xxx property access, if the property is an instance property without an initializer,
// and if we are in a constructor of the same class as the property declaration, assume that
// the property is uninitialized at the top of the control flow.
let assumeUninitialized = false;
if (strictNullChecks && strictPropertyInitialization && left.kind === SyntaxKind.ThisKeyword) {
const declaration = prop && prop.valueDeclaration;
if (declaration && isInstancePropertyWithoutInitializer(declaration)) {
const flowContainer = getControlFlowContainer(node);
if (flowContainer.kind === SyntaxKind.Constructor && flowContainer.parent === declaration.parent) {
assumeUninitialized = true;
}
}
}
const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
error(right, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop));
// Return the declared type to reduce follow-on errors
return propType;
}
const flowType = getFlowTypeOfReference(node, type);
return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType;
}
@@ -22494,6 +22504,7 @@ namespace ts {
if (produceDiagnostics) {
checkIndexConstraints(type);
checkTypeForDuplicateIndexSignatures(node);
checkPropertyInitialization(node);
}
}
@@ -22650,6 +22661,40 @@ namespace ts {
return ok;
}
function checkPropertyInitialization(node: ClassLikeDeclaration) {
if (!strictNullChecks || !strictPropertyInitialization || node.flags & NodeFlags.Ambient) {
return;
}
const constructor = findConstructorDeclaration(node);
for (const member of node.members) {
if (isInstancePropertyWithoutInitializer(member)) {
const propName = (<PropertyDeclaration>member).name;
if (isIdentifier(propName)) {
const type = getTypeOfSymbol(getSymbolOfNode(member));
if (!(type.flags & TypeFlags.Any || getFalsyFlags(type) & TypeFlags.Undefined)) {
if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) {
error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName));
}
}
}
}
}
}
function isInstancePropertyWithoutInitializer(node: Node) {
return node.kind === SyntaxKind.PropertyDeclaration &&
!hasModifier(node, ModifierFlags.Static | ModifierFlags.Abstract) &&
!(<PropertyDeclaration>node).exclamationToken &&
!(<PropertyDeclaration>node).initializer;
}
function isPropertyInitializedInConstructor(propName: Identifier, propType: Type, constructor: ConstructorDeclaration) {
const reference = createPropertyAccess(createThis(), propName);
reference.flowNode = constructor.returnFlowNode;
const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
return !(getFalsyFlags(flowType) & TypeFlags.Undefined);
}
function checkInterfaceDeclaration(node: InterfaceDeclaration) {
// Grammar checking
if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node);
@@ -26072,6 +26117,10 @@ namespace ts {
}
}
if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & NodeFlags.Ambient)) {
return grammarErrorOnNode(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context);
}
if (compilerOptions.module !== ModuleKind.ES2015 && compilerOptions.module !== ModuleKind.ESNext && compilerOptions.module !== ModuleKind.System && !compilerOptions.noEmit &&
!(node.parent.parent.flags & NodeFlags.Ambient) && hasModifier(node.parent.parent, ModifierFlags.Export)) {
checkESModuleMarker(node.name);
@@ -26235,6 +26284,11 @@ namespace ts {
if (node.flags & NodeFlags.Ambient && node.initializer) {
return grammarErrorOnFirstToken(node.initializer, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
}
if (node.exclamationToken && (!isClassLike(node.parent) || !node.type || node.initializer ||
node.flags & NodeFlags.Ambient || hasModifier(node, ModifierFlags.Static | ModifierFlags.Abstract))) {
return grammarErrorOnNode(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context);
}
}
function checkGrammarTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
+7
View File
@@ -277,6 +277,13 @@ namespace ts {
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_checking_of_function_types
},
{
name: "strictPropertyInitialization",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_checking_of_property_initialization_in_classes
},
{
name: "noImplicitThis",
type: "boolean",
+6 -4
View File
@@ -1260,10 +1260,12 @@ namespace ts {
return result;
}
export function arrayToNumericMap<T>(array: ReadonlyArray<T>, makeKey: (value: T) => number): T[] {
const result: T[] = [];
export function arrayToNumericMap<T>(array: ReadonlyArray<T>, makeKey: (value: T) => number): T[];
export function arrayToNumericMap<T, V>(array: ReadonlyArray<T>, makeKey: (value: T) => number, makeValue: (value: T) => V): V[];
export function arrayToNumericMap<T, V>(array: ReadonlyArray<T>, makeKey: (value: T) => number, makeValue?: (value: T) => V): V[] {
const result: V[] = [];
for (const value of array) {
result[makeKey(value)] = value;
result[makeKey(value)] = makeValue ? makeValue(value) : value as any as V;
}
return result;
}
@@ -1967,7 +1969,7 @@ namespace ts {
: moduleKind === ModuleKind.System;
}
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict";
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict";
export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag];
+16
View File
@@ -831,6 +831,10 @@
"category": "Error",
"code": 1254
},
"A definite assignment assertion '!' is not permitted in this context.": {
"category": "Error",
"code": 1255
},
"'with' statements are not allowed in an async function block.": {
"category": "Error",
"code": 1300
@@ -1952,6 +1956,14 @@
"category": "Error",
"code": 2563
},
"Property '{0}' has no initializer and is not definitely assigned in the constructor.": {
"category": "Error",
"code": 2564
},
"Property '{0}' is used before being assigned.": {
"category": "Error",
"code": 2565
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
@@ -3391,6 +3403,10 @@
"category": "Message",
"code": 6186
},
"Enable strict checking of property initialization in classes.": {
"category": "Message",
"code": 6187
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
+21 -10
View File
@@ -99,6 +99,7 @@ namespace ts {
visitNode(cbNode, (<VariableLikeDeclaration>node).dotDotDotToken) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).name) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).questionToken) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).exclamationToken) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).type) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).initializer);
case SyntaxKind.FunctionType:
@@ -5251,9 +5252,17 @@ namespace ts {
return parseIdentifier();
}
function parseVariableDeclaration(): VariableDeclaration {
function parseVariableDeclarationAllowExclamation() {
return parseVariableDeclaration(/*allowExclamation*/ true);
}
function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration {
const node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);
node.name = parseIdentifierOrPattern();
if (allowExclamation && node.name.kind === SyntaxKind.Identifier &&
token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
node.exclamationToken = parseTokenNode();
}
node.type = parseTypeAnnotation();
if (!isInOrOfKeyword(token())) {
node.initializer = parseInitializer();
@@ -5295,7 +5304,8 @@ namespace ts {
const savedDisallowIn = inDisallowInContext();
setDisallowInContext(inForStatementInitializer);
node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations, parseVariableDeclaration);
node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations,
inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation);
setDisallowInContext(savedDisallowIn);
}
@@ -5346,6 +5356,9 @@ namespace ts {
function parsePropertyDeclaration(node: PropertyDeclaration): PropertyDeclaration {
node.kind = SyntaxKind.PropertyDeclaration;
if (!node.questionToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
node.exclamationToken = parseTokenNode();
}
node.type = parseTypeAnnotation();
// For instance properties specifically, since they are evaluated inside the constructor,
@@ -6132,16 +6145,14 @@ namespace ts {
}
// Parses out a JSDoc type expression.
export function parseJSDocTypeExpression(): JSDocTypeExpression;
export function parseJSDocTypeExpression(requireBraces: true): JSDocTypeExpression | undefined;
export function parseJSDocTypeExpression(requireBraces?: boolean): JSDocTypeExpression | undefined {
export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression {
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
if (!parseExpected(SyntaxKind.OpenBraceToken) && requireBraces) {
return undefined;
}
const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken);
result.type = doInsideOfContext(NodeFlags.JSDoc, parseType);
parseExpected(SyntaxKind.CloseBraceToken);
if (!mayOmitBraces || hasBrace) {
parseExpected(SyntaxKind.CloseBraceToken);
}
fixupParentReferences(result);
return finishNode(result);
@@ -6597,7 +6608,7 @@ namespace ts {
const result = <JSDocTypeTag>createNode(SyntaxKind.JSDocTypeTag, atToken.pos);
result.atToken = atToken;
result.tagName = tagName;
result.typeExpression = parseJSDocTypeExpression(/*requireBraces*/ true);
result.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
return finishNode(result);
}
+6 -6
View File
@@ -1227,9 +1227,6 @@ namespace ts {
if (isSourceFileJavaScript(sourceFile)) {
if (!sourceFile.additionalSyntacticDiagnostics) {
sourceFile.additionalSyntacticDiagnostics = getJavaScriptSyntacticDiagnosticsForFile(sourceFile);
if (isCheckJsEnabledForFile(sourceFile, options)) {
sourceFile.additionalSyntacticDiagnostics = concatenate(sourceFile.additionalSyntacticDiagnostics, sourceFile.jsDocDiagnostics);
}
}
return concatenate(sourceFile.additionalSyntacticDiagnostics, sourceFile.parseDiagnostics);
}
@@ -1276,15 +1273,18 @@ namespace ts {
Debug.assert(!!sourceFile.bindDiagnostics);
const isCheckJs = isCheckJsEnabledForFile(sourceFile, options);
// By default, only type-check .ts, .tsx, and 'External' files (external files are added by plugins)
const includeBindAndCheckDiagnostics = sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX ||
sourceFile.scriptKind === ScriptKind.External || isCheckJsEnabledForFile(sourceFile, options);
sourceFile.scriptKind === ScriptKind.External || isCheckJs;
const bindDiagnostics = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray;
const checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray;
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
const diagnostics = bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile);
let diagnostics = bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile);
if (isCheckJs) {
diagnostics = concatenate(diagnostics, sourceFile.jsDocDiagnostics);
}
return filter(diagnostics, shouldReportDiagnostic);
});
}
+11
View File
@@ -1873,7 +1873,17 @@ namespace ts {
return token = SyntaxKind.CommaToken;
case CharacterCodes.dot:
pos++;
if (text.substr(tokenPos, pos + 2) === "...") {
pos += 2;
return token = SyntaxKind.DotDotDotToken;
}
return token = SyntaxKind.DotToken;
case CharacterCodes.exclamation:
pos++;
return token = SyntaxKind.ExclamationToken;
case CharacterCodes.question:
pos++;
return token = SyntaxKind.QuestionToken;
}
if (isIdentifierStart(ch, ScriptTarget.Latest)) {
@@ -1881,6 +1891,7 @@ namespace ts {
while (isIdentifierPart(text.charCodeAt(pos), ScriptTarget.Latest) && pos < end) {
pos++;
}
tokenValue = text.substring(tokenPos, pos);
return token = SyntaxKind.Identifier;
}
else {
+10 -4
View File
@@ -598,6 +598,7 @@ namespace ts {
export type DotDotDotToken = Token<SyntaxKind.DotDotDotToken>;
export type QuestionToken = Token<SyntaxKind.QuestionToken>;
export type ExclamationToken = Token<SyntaxKind.ExclamationToken>;
export type ColonToken = Token<SyntaxKind.ColonToken>;
export type EqualsToken = Token<SyntaxKind.EqualsToken>;
export type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
@@ -761,9 +762,10 @@ namespace ts {
export interface VariableDeclaration extends NamedDeclaration {
kind: SyntaxKind.VariableDeclaration;
parent?: VariableDeclarationList | CatchClause;
name: BindingName; // Declared variable name
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
name: BindingName; // Declared variable name
exclamationToken?: ExclamationToken; // Optional definite assignment assertion
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
}
export interface VariableDeclarationList extends Node {
@@ -801,8 +803,9 @@ namespace ts {
export interface PropertyDeclaration extends ClassElement, JSDocContainer {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken; // Present for use with reporting a grammar error
name: PropertyName;
questionToken?: QuestionToken; // Present for use with reporting a grammar error
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression; // Optional initializer
}
@@ -860,6 +863,7 @@ namespace ts {
dotDotDotToken?: DotDotDotToken;
name: DeclarationName;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression;
}
@@ -947,6 +951,7 @@ namespace ts {
kind: SyntaxKind.Constructor;
parent?: ClassDeclaration | ClassExpression;
body?: FunctionBody;
/* @internal */ returnFlowNode?: FlowNode;
}
/** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */
@@ -3854,6 +3859,7 @@ namespace ts {
strict?: boolean;
strictFunctionTypes?: boolean; // Always combine with strict property
strictNullChecks?: boolean; // Always combine with strict property
strictPropertyInitialization?: boolean; // Always combine with strict property
/* @internal */ stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
+1 -10
View File
@@ -5078,16 +5078,7 @@ namespace ts {
}
export function isStringTextContainingNode(node: Node) {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
case SyntaxKind.TemplateTail:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return true;
default:
return false;
}
return node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind);
}
// Identifiers
+2 -2
View File
@@ -208,8 +208,8 @@ namespace Harness.Parallel.Host {
workers.push(child);
}
// It's only really worth doing an initial batching if there are a ton of files to go through
if (totalFiles > 1000) {
// It's only really worth doing an initial batching if there are a ton of files to go through (and they have estimates)
if (totalFiles > 1000 && batchSize > 0) {
console.log("Batching initial test lists...");
const batches: { runner: TestRunnerKind | "unittest", file: string, size: number }[][] = new Array(batchCount);
const doneBatching = new Array(batchCount);
+212 -62
View File
@@ -82,8 +82,8 @@ interface ConstrainVideoFacingModeParameters {
ideal?: VideoFacingModeEnum | VideoFacingModeEnum[];
}
interface CustomEventInit extends EventInit {
detail?: any;
interface CustomEventInit<T = any> extends EventInit {
detail?: T;
}
interface DeviceAccelerationDict {
@@ -696,7 +696,7 @@ interface PaymentDetails {
interface PaymentDetailsModifier {
additionalDisplayItems?: PaymentItem[];
data?: any;
supportedMethods: string[];
supportedMethods: string | string[];
total?: PaymentItem;
}
@@ -708,7 +708,7 @@ interface PaymentItem {
interface PaymentMethodData {
data?: any;
supportedMethods: string[];
supportedMethods: string | string[];
}
interface PaymentOptions {
@@ -1597,6 +1597,7 @@ interface CanvasRenderingContext2D extends Object, CanvasPathMethods {
beginPath(): void;
clearRect(x: number, y: number, w: number, h: number): void;
clip(fillRule?: CanvasFillRule): void;
clip(path: Path2D, fillRule?: CanvasFillRule): void;
createImageData(imageDataOrSw: number | ImageData, sh?: number): ImageData;
createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
createPattern(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, repetition: string): CanvasPattern;
@@ -1606,11 +1607,13 @@ interface CanvasRenderingContext2D extends Object, CanvasPathMethods {
drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number, dstW: number, dstH: number): void;
drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, srcX: number, srcY: number, srcW: number, srcH: number, dstX: number, dstY: number, dstW: number, dstH: number): void;
fill(fillRule?: CanvasFillRule): void;
fill(path: Path2D, fillRule?: CanvasFillRule): void;
fillRect(x: number, y: number, w: number, h: number): void;
fillText(text: string, x: number, y: number, maxWidth?: number): void;
getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;
getLineDash(): number[];
isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean;
isPointInPath(path: Path2D, x: number, y: number, fillRule?: CanvasFillRule): boolean;
measureText(text: string): TextMetrics;
putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void;
restore(): void;
@@ -2374,14 +2377,14 @@ declare var CSSSupportsRule: {
new(): CSSSupportsRule;
};
interface CustomEvent extends Event {
readonly detail: any;
initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: any): void;
interface CustomEvent<T = any> extends Event {
readonly detail: T;
initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: T): void;
}
declare var CustomEvent: {
prototype: CustomEvent;
new(typeArg: string, eventInitDict?: CustomEventInit): CustomEvent;
new<T>(typeArg: string, eventInitDict?: CustomEventInit<T>): CustomEvent<T>;
};
interface DataCue extends TextTrackCue {
@@ -3240,7 +3243,8 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven
* Retrieves a collection of objects based on the specified element name.
* @param name Specifies the name of an element.
*/
getElementsByTagName<K extends keyof ElementListTagNameMap>(tagname: K): ElementListTagNameMap[K];
getElementsByTagName<K extends keyof HTMLElementTagNameMap>(tagname: K): NodeListOf<HTMLElementTagNameMap[K]>;
getElementsByTagName<K extends keyof SVGElementTagNameMap>(tagname: K): NodeListOf<SVGElementTagNameMap[K]>;
getElementsByTagName(tagname: string): NodeListOf<Element>;
getElementsByTagNameNS(namespaceURI: "http://www.w3.org/1999/xhtml", localName: string): HTMLCollectionOf<HTMLElement>;
getElementsByTagNameNS(namespaceURI: "http://www.w3.org/2000/svg", localName: string): HTMLCollectionOf<SVGElement>;
@@ -3597,7 +3601,8 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
getAttributeNS(namespaceURI: string, localName: string): string;
getBoundingClientRect(): ClientRect;
getClientRects(): ClientRectList;
getElementsByTagName<K extends keyof ElementListTagNameMap>(name: K): ElementListTagNameMap[K];
getElementsByTagName<K extends keyof HTMLElementTagNameMap>(name: K): NodeListOf<HTMLElementTagNameMap[K]>;
getElementsByTagName<K extends keyof SVGElementTagNameMap>(name: K): NodeListOf<SVGElementTagNameMap[K]>;
getElementsByTagName(name: string): NodeListOf<Element>;
getElementsByTagNameNS(namespaceURI: "http://www.w3.org/1999/xhtml", localName: string): HTMLCollectionOf<HTMLElement>;
getElementsByTagNameNS(namespaceURI: "http://www.w3.org/2000/svg", localName: string): HTMLCollectionOf<SVGElement>;
@@ -3626,6 +3631,8 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
webkitRequestFullScreen(): void;
getElementsByClassName(classNames: string): NodeListOf<Element>;
matches(selector: string): boolean;
closest<K extends keyof HTMLElementTagNameMap>(selector: K): HTMLElementTagNameMap[K] | null;
closest<K extends keyof SVGElementTagNameMap>(selector: K): SVGElementTagNameMap[K] | null;
closest(selector: string): Element | null;
scrollIntoView(arg?: boolean | ScrollIntoViewOptions): void;
scroll(options?: ScrollToOptions): void;
@@ -5520,6 +5527,7 @@ interface HTMLLabelElement extends HTMLElement {
* Sets or retrieves the object to which the given label object is assigned.
*/
htmlFor: string;
readonly control: HTMLInputElement | null;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLabelElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLabelElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
@@ -9711,7 +9719,7 @@ interface ServiceWorkerContainer extends EventTarget {
oncontrollerchange: (this: ServiceWorkerContainer, ev: Event) => any;
onmessage: (this: ServiceWorkerContainer, ev: ServiceWorkerMessageEvent) => any;
readonly ready: Promise<ServiceWorkerRegistration>;
getRegistration(): Promise<ServiceWorkerRegistration | undefined>;
getRegistration(clientURL?: USVString): Promise<ServiceWorkerRegistration | undefined>;
getRegistrations(): Promise<ServiceWorkerRegistration[]>;
register(scriptURL: USVString, options?: RegistrationOptions): Promise<ServiceWorkerRegistration>;
addEventListener<K extends keyof ServiceWorkerContainerEventMap>(type: K, listener: (this: ServiceWorkerContainer, ev: ServiceWorkerContainerEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
@@ -12477,7 +12485,29 @@ interface WebGLRenderingContext {
getBufferParameter(target: number, pname: number): any;
getContextAttributes(): WebGLContextAttributes;
getError(): number;
getExtension(name: string): any;
getExtension(extensionName: "EXT_blend_minmax"): EXT_blend_minmax | null;
getExtension(extensionName: "EXT_texture_filter_anisotropic"): EXT_texture_filter_anisotropic | null;
getExtension(extensionName: "EXT_frag_depth"): EXT_frag_depth | null;
getExtension(extensionName: "EXT_shader_texture_lod"): EXT_shader_texture_lod | null;
getExtension(extensionName: "EXT_sRGB"): EXT_sRGB | null;
getExtension(extensionName: "OES_vertex_array_object"): OES_vertex_array_object | null;
getExtension(extensionName: "WEBGL_color_buffer_float"): WEBGL_color_buffer_float | null;
getExtension(extensionName: "WEBGL_compressed_texture_astc"): WEBGL_compressed_texture_astc | null;
getExtension(extensionName: "WEBGL_compressed_texture_s3tc_srgb"): WEBGL_compressed_texture_s3tc_srgb | null;
getExtension(extensionName: "WEBGL_debug_shaders"): WEBGL_debug_shaders | null;
getExtension(extensionName: "WEBGL_draw_buffers"): WEBGL_draw_buffers | null;
getExtension(extensionName: "WEBGL_lose_context"): WEBGL_lose_context | null;
getExtension(extensionName: "WEBGL_depth_texture"): WEBGL_depth_texture | null;
getExtension(extensionName: "WEBGL_debug_renderer_info"): WEBGL_debug_renderer_info | null;
getExtension(extensionName: "WEBGL_compressed_texture_s3tc"): WEBGL_compressed_texture_s3tc | null;
getExtension(extensionName: "OES_texture_half_float_linear"): OES_texture_half_float_linear | null;
getExtension(extensionName: "OES_texture_half_float"): OES_texture_half_float | null;
getExtension(extensionName: "OES_texture_float_linear"): OES_texture_float_linear | null;
getExtension(extensionName: "OES_texture_float"): OES_texture_float | null;
getExtension(extensionName: "OES_standard_derivatives"): OES_standard_derivatives | null;
getExtension(extensionName: "OES_element_index_uint"): OES_element_index_uint | null;
getExtension(extensionName: "ANGLE_instanced_arrays"): ANGLE_instanced_arrays | null;
getExtension(extensionName: string): any;
getFramebufferAttachmentParameter(target: number, attachment: number, pname: number): any;
getParameter(pname: number): any;
getProgramInfoLog(program: WebGLProgram | null): string | null;
@@ -14104,9 +14134,11 @@ interface NavigatorUserMedia {
}
interface NodeSelector {
querySelector<K extends keyof ElementTagNameMap>(selectors: K): ElementTagNameMap[K] | null;
querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
querySelector<E extends Element = Element>(selectors: string): E | null;
querySelectorAll<K extends keyof ElementListTagNameMap>(selectors: K): ElementListTagNameMap[K];
querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;
querySelectorAll<K extends keyof SVGElementTagNameMap>(selectors: K): NodeListOf<SVGElementTagNameMap[K]>;
querySelectorAll<E extends Element = Element>(selectors: string): NodeListOf<E>;
}
@@ -14625,6 +14657,128 @@ declare var HTMLSummaryElement: {
new(): HTMLSummaryElement;
};
interface EXT_blend_minmax {
readonly MIN_EXT: number;
readonly MAX_EXT: number;
}
interface EXT_frag_depth {
}
interface EXT_shader_texture_lod {
}
interface EXT_sRGB {
readonly SRGB_EXT: number;
readonly SRGB_ALPHA_EXT: number;
readonly SRGB8_ALPHA8_EXT: number;
readonly FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: number;
}
interface OES_vertex_array_object {
readonly VERTEX_ARRAY_BINDING_OES: number;
createVertexArrayOES(): WebGLVertexArrayObjectOES;
deleteVertexArrayOES(arrayObject: WebGLVertexArrayObjectOES): void;
isVertexArrayOES(value: any): value is WebGLVertexArrayObjectOES;
bindVertexArrayOES(arrayObject: WebGLVertexArrayObjectOES): void;
}
interface WebGLVertexArrayObjectOES {
}
interface WEBGL_color_buffer_float {
readonly RGBA32F_EXT: number;
readonly RGB32F_EXT: number;
readonly FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: number;
readonly UNSIGNED_NORMALIZED_EXT: number;
}
interface WEBGL_compressed_texture_astc {
readonly COMPRESSED_RGBA_ASTC_4x4_KHR: number;
readonly COMPRESSED_RGBA_ASTC_5x4_KHR: number;
readonly COMPRESSED_RGBA_ASTC_5x5_KHR: number;
readonly COMPRESSED_RGBA_ASTC_6x5_KHR: number;
readonly COMPRESSED_RGBA_ASTC_6x6_KHR: number;
readonly COMPRESSED_RGBA_ASTC_8x5_KHR: number;
readonly COMPRESSED_RGBA_ASTC_8x6_KHR: number;
readonly COMPRESSED_RGBA_ASTC_8x8_KHR: number;
readonly COMPRESSED_RGBA_ASTC_10x5_KHR: number;
readonly COMPRESSED_RGBA_ASTC_10x6_KHR: number;
readonly COMPRESSED_RGBA_ASTC_10x8_KHR: number;
readonly COMPRESSED_RGBA_ASTC_10x10_KHR: number;
readonly COMPRESSED_RGBA_ASTC_12x10_KHR: number;
readonly COMPRESSED_RGBA_ASTC_12x12_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: number;
readonly COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: number;
getSupportedProfiles(): string[];
}
interface WEBGL_compressed_texture_s3tc_srgb {
readonly COMPRESSED_SRGB_S3TC_DXT1_EXT: number;
readonly COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: number;
readonly COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: number;
readonly COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: number;
}
interface WEBGL_debug_shaders {
getTranslatedShaderSource(shader: WebGLShader): string;
}
interface WEBGL_draw_buffers {
readonly COLOR_ATTACHMENT0_WEBGL: number;
readonly COLOR_ATTACHMENT1_WEBGL: number;
readonly COLOR_ATTACHMENT2_WEBGL: number;
readonly COLOR_ATTACHMENT3_WEBGL: number;
readonly COLOR_ATTACHMENT4_WEBGL: number;
readonly COLOR_ATTACHMENT5_WEBGL: number;
readonly COLOR_ATTACHMENT6_WEBGL: number;
readonly COLOR_ATTACHMENT7_WEBGL: number;
readonly COLOR_ATTACHMENT8_WEBGL: number;
readonly COLOR_ATTACHMENT9_WEBGL: number;
readonly COLOR_ATTACHMENT10_WEBGL: number;
readonly COLOR_ATTACHMENT11_WEBGL: number;
readonly COLOR_ATTACHMENT12_WEBGL: number;
readonly COLOR_ATTACHMENT13_WEBGL: number;
readonly COLOR_ATTACHMENT14_WEBGL: number;
readonly COLOR_ATTACHMENT15_WEBGL: number;
readonly DRAW_BUFFER0_WEBGL: number;
readonly DRAW_BUFFER1_WEBGL: number;
readonly DRAW_BUFFER2_WEBGL: number;
readonly DRAW_BUFFER3_WEBGL: number;
readonly DRAW_BUFFER4_WEBGL: number;
readonly DRAW_BUFFER5_WEBGL: number;
readonly DRAW_BUFFER6_WEBGL: number;
readonly DRAW_BUFFER7_WEBGL: number;
readonly DRAW_BUFFER8_WEBGL: number;
readonly DRAW_BUFFER9_WEBGL: number;
readonly DRAW_BUFFER10_WEBGL: number;
readonly DRAW_BUFFER11_WEBGL: number;
readonly DRAW_BUFFER12_WEBGL: number;
readonly DRAW_BUFFER13_WEBGL: number;
readonly DRAW_BUFFER14_WEBGL: number;
readonly DRAW_BUFFER15_WEBGL: number;
readonly MAX_COLOR_ATTACHMENTS_WEBGL: number;
readonly MAX_DRAW_BUFFERS_WEBGL: number;
drawBuffersWEBGL(buffers: number[]): void;
}
interface WEBGL_lose_context {
loseContext(): void;
restoreContext(): void;
}
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface DecodeErrorCallback {
@@ -14692,28 +14846,46 @@ interface VoidFunction {
}
interface HTMLElementTagNameMap {
"a": HTMLAnchorElement;
"abbr": HTMLElement;
"acronym": HTMLElement;
"address": HTMLElement;
"applet": HTMLAppletElement;
"area": HTMLAreaElement;
"article": HTMLElement;
"aside": HTMLElement;
"audio": HTMLAudioElement;
"b": HTMLElement;
"base": HTMLBaseElement;
"basefont": HTMLBaseFontElement;
"bdo": HTMLElement;
"big": HTMLElement;
"blockquote": HTMLQuoteElement;
"body": HTMLBodyElement;
"br": HTMLBRElement;
"button": HTMLButtonElement;
"canvas": HTMLCanvasElement;
"caption": HTMLTableCaptionElement;
"center": HTMLElement;
"cite": HTMLElement;
"code": HTMLElement;
"col": HTMLTableColElement;
"colgroup": HTMLTableColElement;
"data": HTMLDataElement;
"datalist": HTMLDataListElement;
"dd": HTMLElement;
"del": HTMLModElement;
"dfn": HTMLElement;
"dir": HTMLDirectoryElement;
"div": HTMLDivElement;
"dl": HTMLDListElement;
"dt": HTMLElement;
"em": HTMLElement;
"embed": HTMLEmbedElement;
"fieldset": HTMLFieldSetElement;
"figcaption": HTMLElement;
"figure": HTMLElement;
"font": HTMLFontElement;
"footer": HTMLElement;
"form": HTMLFormElement;
"frame": HTMLFrameElement;
"frameset": HTMLFrameSetElement;
@@ -14724,24 +14896,34 @@ interface HTMLElementTagNameMap {
"h5": HTMLHeadingElement;
"h6": HTMLHeadingElement;
"head": HTMLHeadElement;
"header": HTMLElement;
"hgroup": HTMLElement;
"hr": HTMLHRElement;
"html": HTMLHtmlElement;
"i": HTMLElement;
"iframe": HTMLIFrameElement;
"img": HTMLImageElement;
"input": HTMLInputElement;
"ins": HTMLModElement;
"isindex": HTMLUnknownElement;
"kbd": HTMLElement;
"keygen": HTMLElement;
"label": HTMLLabelElement;
"legend": HTMLLegendElement;
"li": HTMLLIElement;
"link": HTMLLinkElement;
"listing": HTMLPreElement;
"map": HTMLMapElement;
"mark": HTMLElement;
"marquee": HTMLMarqueeElement;
"menu": HTMLMenuElement;
"meta": HTMLMetaElement;
"meter": HTMLMeterElement;
"nav": HTMLElement;
"nextid": HTMLUnknownElement;
"nobr": HTMLElement;
"noframes": HTMLElement;
"noscript": HTMLElement;
"object": HTMLObjectElement;
"ol": HTMLOListElement;
"optgroup": HTMLOptGroupElement;
@@ -14750,14 +14932,25 @@ interface HTMLElementTagNameMap {
"p": HTMLParagraphElement;
"param": HTMLParamElement;
"picture": HTMLPictureElement;
"plaintext": HTMLElement;
"pre": HTMLPreElement;
"progress": HTMLProgressElement;
"q": HTMLQuoteElement;
"rt": HTMLElement;
"ruby": HTMLElement;
"s": HTMLElement;
"samp": HTMLElement;
"script": HTMLScriptElement;
"section": HTMLElement;
"select": HTMLSelectElement;
"small": HTMLElement;
"source": HTMLSourceElement;
"span": HTMLSpanElement;
"strike": HTMLElement;
"strong": HTMLElement;
"style": HTMLStyleElement;
"sub": HTMLElement;
"sup": HTMLElement;
"table": HTMLTableElement;
"tbody": HTMLTableSectionElement;
"td": HTMLTableDataCellElement;
@@ -14770,33 +14963,22 @@ interface HTMLElementTagNameMap {
"title": HTMLTitleElement;
"tr": HTMLTableRowElement;
"track": HTMLTrackElement;
"tt": HTMLElement;
"u": HTMLElement;
"ul": HTMLUListElement;
"var": HTMLElement;
"video": HTMLVideoElement;
"wbr": HTMLElement;
"x-ms-webview": MSHTMLWebViewElement;
"xmp": HTMLPreElement;
}
interface ElementTagNameMap extends HTMLElementTagNameMap {
"abbr": HTMLElement;
"acronym": HTMLElement;
"address": HTMLElement;
"article": HTMLElement;
"aside": HTMLElement;
"b": HTMLElement;
"bdo": HTMLElement;
"big": HTMLElement;
"center": HTMLElement;
interface SVGElementTagNameMap {
"circle": SVGCircleElement;
"cite": HTMLElement;
"clippath": SVGClipPathElement;
"code": HTMLElement;
"dd": HTMLElement;
"defs": SVGDefsElement;
"desc": SVGDescElement;
"dfn": HTMLElement;
"dt": HTMLElement;
"ellipse": SVGEllipseElement;
"em": HTMLElement;
"feblend": SVGFEBlendElement;
"fecolormatrix": SVGFEColorMatrixElement;
"fecomponenttransfer": SVGFEComponentTransferElement;
@@ -14821,64 +15003,32 @@ interface ElementTagNameMap extends HTMLElementTagNameMap {
"fespotlight": SVGFESpotLightElement;
"fetile": SVGFETileElement;
"feturbulence": SVGFETurbulenceElement;
"figcaption": HTMLElement;
"figure": HTMLElement;
"filter": SVGFilterElement;
"footer": HTMLElement;
"foreignobject": SVGForeignObjectElement;
"g": SVGGElement;
"header": HTMLElement;
"hgroup": HTMLElement;
"i": HTMLElement;
"image": SVGImageElement;
"kbd": HTMLElement;
"keygen": HTMLElement;
"line": SVGLineElement;
"lineargradient": SVGLinearGradientElement;
"mark": HTMLElement;
"marker": SVGMarkerElement;
"mask": SVGMaskElement;
"metadata": SVGMetadataElement;
"nav": HTMLElement;
"nobr": HTMLElement;
"noframes": HTMLElement;
"noscript": HTMLElement;
"path": SVGPathElement;
"pattern": SVGPatternElement;
"plaintext": HTMLElement;
"polygon": SVGPolygonElement;
"polyline": SVGPolylineElement;
"radialgradient": SVGRadialGradientElement;
"rect": SVGRectElement;
"rt": HTMLElement;
"ruby": HTMLElement;
"s": HTMLElement;
"samp": HTMLElement;
"section": HTMLElement;
"small": HTMLElement;
"stop": SVGStopElement;
"strike": HTMLElement;
"strong": HTMLElement;
"sub": HTMLElement;
"sup": HTMLElement;
"svg": SVGSVGElement;
"switch": SVGSwitchElement;
"symbol": SVGSymbolElement;
"text": SVGTextElement;
"textpath": SVGTextPathElement;
"tspan": SVGTSpanElement;
"tt": HTMLElement;
"u": HTMLElement;
"use": SVGUseElement;
"var": HTMLElement;
"view": SVGViewElement;
"wbr": HTMLElement;
}
type ElementListTagNameMap = {
[key in keyof ElementTagNameMap]: NodeListOf<ElementTagNameMap[key]>
};
declare var Audio: { new(src?: string): HTMLAudioElement; };
declare var Image: { new(width?: number, height?: number): HTMLImageElement; };
declare var Option: { new(text?: string, value?: string, defaultSelected?: boolean, selected?: boolean): HTMLOptionElement; };
+345 -366
View File
@@ -1,177 +1,50 @@
namespace ts {
/// Classifier
export function createClassifier(): Classifier {
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
/// We do not have a full parser support to know when we should parse a regex or not
/// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where
/// we have a series of divide operator. this list allows us to be more accurate by ruling out
/// locations where a regexp cannot exist.
const noRegexTable: boolean[] = [];
noRegexTable[SyntaxKind.Identifier] = true;
noRegexTable[SyntaxKind.StringLiteral] = true;
noRegexTable[SyntaxKind.NumericLiteral] = true;
noRegexTable[SyntaxKind.RegularExpressionLiteral] = true;
noRegexTable[SyntaxKind.ThisKeyword] = true;
noRegexTable[SyntaxKind.PlusPlusToken] = true;
noRegexTable[SyntaxKind.MinusMinusToken] = true;
noRegexTable[SyntaxKind.CloseParenToken] = true;
noRegexTable[SyntaxKind.CloseBracketToken] = true;
noRegexTable[SyntaxKind.CloseBraceToken] = true;
noRegexTable[SyntaxKind.TrueKeyword] = true;
noRegexTable[SyntaxKind.FalseKeyword] = true;
// Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact)
// classification on template strings. Because of the context free nature of templates,
// the only precise way to classify a template portion would be by propagating the stack across
// lines, just as we do with the end-of-line state. However, this is a burden for implementers,
// and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead
// flatten any nesting when the template stack is non-empty and encode it in the end-of-line state.
// Situations in which this fails are
// 1) When template strings are nested across different lines:
// `hello ${ `world
// ` }`
//
// Where on the second line, you will get the closing of a template,
// a closing curly, and a new template.
//
// 2) When substitution expressions have curly braces and the curly brace falls on the next line:
// `hello ${ () => {
// return "world" } } `
//
// Where on the second line, you will get the 'return' keyword,
// a string literal, and a template end consisting of '} } `'.
const templateStack: SyntaxKind[] = [];
/** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */
function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) {
if (isAccessibilityModifier(keyword1)) {
if (keyword2 === SyntaxKind.GetKeyword ||
keyword2 === SyntaxKind.SetKeyword ||
keyword2 === SyntaxKind.ConstructorKeyword ||
keyword2 === SyntaxKind.StaticKeyword) {
// Allow things like "public get", "public constructor" and "public static".
// These are all legal.
return true;
}
// Any other keyword following "public" is actually an identifier an not a real
// keyword.
return false;
}
// Assume any other keyword combination is legal. This can be refined in the future
// if there are more cases we want the classifier to be better at.
return true;
}
function convertClassifications(classifications: Classifications, text: string): ClassificationResult {
const entries: ClassificationInfo[] = [];
const dense = classifications.spans;
let lastEnd = 0;
for (let i = 0; i < dense.length; i += 3) {
const start = dense[i];
const length = dense[i + 1];
const type = <ClassificationType>dense[i + 2];
// Make a whitespace entry between the last item and this one.
if (lastEnd >= 0) {
const whitespaceLength = start - lastEnd;
if (whitespaceLength > 0) {
entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace });
}
}
entries.push({ length, classification: convertClassification(type) });
lastEnd = start + length;
}
const whitespaceLength = text.length - lastEnd;
if (whitespaceLength > 0) {
entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace });
}
return { entries, finalLexState: classifications.endOfLineState };
}
function convertClassification(type: ClassificationType): TokenClass {
switch (type) {
case ClassificationType.comment: return TokenClass.Comment;
case ClassificationType.keyword: return TokenClass.Keyword;
case ClassificationType.numericLiteral: return TokenClass.NumberLiteral;
case ClassificationType.operator: return TokenClass.Operator;
case ClassificationType.stringLiteral: return TokenClass.StringLiteral;
case ClassificationType.whiteSpace: return TokenClass.Whitespace;
case ClassificationType.punctuation: return TokenClass.Punctuation;
case ClassificationType.identifier:
case ClassificationType.className:
case ClassificationType.enumName:
case ClassificationType.interfaceName:
case ClassificationType.moduleName:
case ClassificationType.typeParameterName:
case ClassificationType.typeAliasName:
case ClassificationType.text:
case ClassificationType.parameterName:
default:
return TokenClass.Identifier;
}
}
function getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult {
return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text);
return convertClassificationsToResult(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text);
}
// If there is a syntactic classifier ('syntacticClassifierAbsent' is false),
// we will be more conservative in order to avoid conflicting with the syntactic classifier.
function getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications {
let offset = 0;
let token = SyntaxKind.Unknown;
let lastNonTriviaToken = SyntaxKind.Unknown;
// Empty out the template stack for reuse.
while (templateStack.length > 0) {
templateStack.pop();
}
// If we're in a string literal, then prepend: "\
// (and a newline). That way when we lex we'll think we're still in a string literal.
// Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact)
// classification on template strings. Because of the context free nature of templates,
// the only precise way to classify a template portion would be by propagating the stack across
// lines, just as we do with the end-of-line state. However, this is a burden for implementers,
// and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead
// flatten any nesting when the template stack is non-empty and encode it in the end-of-line state.
// Situations in which this fails are
// 1) When template strings are nested across different lines:
// `hello ${ `world
// ` }`
//
// If we're in a multiline comment, then prepend: /*
// (and a newline). That way when we lex we'll think we're still in a multiline comment.
switch (lexState) {
case EndOfLineState.InDoubleQuoteStringLiteral:
text = "\"\\\n" + text;
offset = 3;
break;
case EndOfLineState.InSingleQuoteStringLiteral:
text = "'\\\n" + text;
offset = 3;
break;
case EndOfLineState.InMultiLineCommentTrivia:
text = "/*\n" + text;
offset = 3;
break;
case EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate:
text = "`\n" + text;
offset = 2;
break;
case EndOfLineState.InTemplateMiddleOrTail:
text = "}\n" + text;
offset = 2;
// falls through
case EndOfLineState.InTemplateSubstitutionPosition:
templateStack.push(SyntaxKind.TemplateHead);
break;
// Where on the second line, you will get the closing of a template,
// a closing curly, and a new template.
//
// 2) When substitution expressions have curly braces and the curly brace falls on the next line:
// `hello ${ () => {
// return "world" } } `
//
// Where on the second line, you will get the 'return' keyword,
// a string literal, and a template end consisting of '} } `'.
const templateStack: SyntaxKind[] = [];
const { prefix, pushTemplate } = getPrefixFromLexState(lexState);
text = prefix + text;
const offset = prefix.length;
if (pushTemplate) {
templateStack.push(SyntaxKind.TemplateHead);
}
scanner.setText(text);
const result: Classifications = {
endOfLineState: EndOfLineState.None,
spans: []
};
let endOfLineState = EndOfLineState.None;
const spans: number[] = [];
// We can run into an unfortunate interaction between the lexical and syntactic classifier
// when the user is typing something generic. Consider the case where the user types:
@@ -196,57 +69,65 @@ namespace ts {
do {
token = scanner.scan();
if (!isTrivia(token)) {
if ((token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) && !noRegexTable[lastNonTriviaToken]) {
if (scanner.reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
handleToken();
lastNonTriviaToken = token;
}
const end = scanner.getTextPos();
pushEncodedClassification(scanner.getTokenPos(), end, offset, classFromKind(token), spans);
if (end >= text.length) {
const end = getNewEndOfLineState(scanner, token, lastOrUndefined(templateStack));
if (end !== undefined) {
endOfLineState = end;
}
}
} while (token !== SyntaxKind.EndOfFileToken);
function handleToken(): void {
switch (token) {
case SyntaxKind.SlashToken:
case SyntaxKind.SlashEqualsToken:
if (!noRegexTable[lastNonTriviaToken] && scanner.reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
token = SyntaxKind.RegularExpressionLiteral;
}
}
else if (lastNonTriviaToken === SyntaxKind.DotToken && isKeyword(token)) {
token = SyntaxKind.Identifier;
}
else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) {
// We have two keywords in a row. Only treat the second as a keyword if
// it's a sequence that could legally occur in the language. Otherwise
// treat it as an identifier. This way, if someone writes "private var"
// we recognize that 'var' is actually an identifier here.
token = SyntaxKind.Identifier;
}
else if (lastNonTriviaToken === SyntaxKind.Identifier &&
token === SyntaxKind.LessThanToken) {
// Could be the start of something generic. Keep track of that by bumping
// up the current count of generic contexts we may be in.
angleBracketStack++;
}
else if (token === SyntaxKind.GreaterThanToken && angleBracketStack > 0) {
// If we think we're currently in something generic, then mark that that
// generic entity is complete.
angleBracketStack--;
}
else if (token === SyntaxKind.AnyKeyword ||
token === SyntaxKind.StringKeyword ||
token === SyntaxKind.NumberKeyword ||
token === SyntaxKind.BooleanKeyword ||
token === SyntaxKind.SymbolKeyword) {
break;
case SyntaxKind.LessThanToken:
if (lastNonTriviaToken === SyntaxKind.Identifier) {
// Could be the start of something generic. Keep track of that by bumping
// up the current count of generic contexts we may be in.
angleBracketStack++;
}
break;
case SyntaxKind.GreaterThanToken:
if (angleBracketStack > 0) {
// If we think we're currently in something generic, then mark that that
// generic entity is complete.
angleBracketStack--;
}
break;
case SyntaxKind.AnyKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
if (angleBracketStack > 0 && !syntacticClassifierAbsent) {
// If it looks like we're could be in something generic, don't classify this
// as a keyword. We may just get overwritten by the syntactic classifier,
// causing a noisy experience for the user.
token = SyntaxKind.Identifier;
}
}
else if (token === SyntaxKind.TemplateHead) {
break;
case SyntaxKind.TemplateHead:
templateStack.push(token);
}
else if (token === SyntaxKind.OpenBraceToken) {
break;
case SyntaxKind.OpenBraceToken:
// If we don't have anything on the template stack,
// then we aren't trying to keep track of a previously scanned template head.
if (templateStack.length > 0) {
templateStack.push(token);
}
}
else if (token === SyntaxKind.CloseBraceToken) {
break;
case SyntaxKind.CloseBraceToken:
// If we don't have anything on the template stack,
// then we aren't trying to keep track of a previously scanned template head.
if (templateStack.length > 0) {
@@ -268,202 +149,300 @@ namespace ts {
templateStack.pop();
}
}
}
lastNonTriviaToken = token;
}
processToken();
}
while (token !== SyntaxKind.EndOfFileToken);
return result;
function processToken(): void {
const start = scanner.getTokenPos();
const end = scanner.getTextPos();
addResult(start, end, classFromKind(token));
if (end >= text.length) {
if (token === SyntaxKind.StringLiteral) {
// Check to see if we finished up on a multiline string literal.
const tokenText = scanner.getTokenText();
if (scanner.isUnterminated()) {
const lastCharIndex = tokenText.length - 1;
let numBackslashes = 0;
while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) {
numBackslashes++;
}
// If we have an odd number of backslashes, then the multiline string is unclosed
if (numBackslashes & 1) {
const quoteChar = tokenText.charCodeAt(0);
result.endOfLineState = quoteChar === CharacterCodes.doubleQuote
? EndOfLineState.InDoubleQuoteStringLiteral
: EndOfLineState.InSingleQuoteStringLiteral;
}
break;
default:
if (!isKeyword(token)) {
break;
}
}
else if (token === SyntaxKind.MultiLineCommentTrivia) {
// Check to see if the multiline comment was unclosed.
if (scanner.isUnterminated()) {
result.endOfLineState = EndOfLineState.InMultiLineCommentTrivia;
if (lastNonTriviaToken === SyntaxKind.DotToken) {
token = SyntaxKind.Identifier;
}
}
else if (isTemplateLiteralKind(token)) {
if (scanner.isUnterminated()) {
if (token === SyntaxKind.TemplateTail) {
result.endOfLineState = EndOfLineState.InTemplateMiddleOrTail;
}
else if (token === SyntaxKind.NoSubstitutionTemplateLiteral) {
result.endOfLineState = EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate;
}
else {
Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
}
else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) {
// We have two keywords in a row. Only treat the second as a keyword if
// it's a sequence that could legally occur in the language. Otherwise
// treat it as an identifier. This way, if someone writes "private var"
// we recognize that 'var' is actually an identifier here.
token = SyntaxKind.Identifier;
}
}
}
return { endOfLineState, spans };
}
return { getClassificationsForLine, getEncodedLexicalClassifications };
}
/// We do not have a full parser support to know when we should parse a regex or not
/// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where
/// we have a series of divide operator. this list allows us to be more accurate by ruling out
/// locations where a regexp cannot exist.
const noRegexTable: true[] = ts.arrayToNumericMap<SyntaxKind, true>([
SyntaxKind.Identifier,
SyntaxKind.StringLiteral,
SyntaxKind.NumericLiteral,
SyntaxKind.RegularExpressionLiteral,
SyntaxKind.ThisKeyword,
SyntaxKind.PlusPlusToken,
SyntaxKind.MinusMinusToken,
SyntaxKind.CloseParenToken,
SyntaxKind.CloseBracketToken,
SyntaxKind.CloseBraceToken,
SyntaxKind.TrueKeyword,
SyntaxKind.FalseKeyword,
], token => token, () => true);
function getNewEndOfLineState(scanner: Scanner, token: SyntaxKind, lastOnTemplateStack: SyntaxKind | undefined): EndOfLineState | undefined {
switch (token) {
case SyntaxKind.StringLiteral: {
// Check to see if we finished up on a multiline string literal.
if (!scanner.isUnterminated()) return undefined;
const tokenText = scanner.getTokenText();
const lastCharIndex = tokenText.length - 1;
let numBackslashes = 0;
while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) {
numBackslashes++;
}
// If we have an odd number of backslashes, then the multiline string is unclosed
if ((numBackslashes & 1) === 0) return undefined;
return tokenText.charCodeAt(0) === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral : EndOfLineState.InSingleQuoteStringLiteral;
}
case SyntaxKind.MultiLineCommentTrivia:
// Check to see if the multiline comment was unclosed.
return scanner.isUnterminated() ? EndOfLineState.InMultiLineCommentTrivia : undefined;
default:
if (isTemplateLiteralKind(token)) {
if (!scanner.isUnterminated()) {
return undefined;
}
else if (templateStack.length > 0 && lastOrUndefined(templateStack) === SyntaxKind.TemplateHead) {
result.endOfLineState = EndOfLineState.InTemplateSubstitutionPosition;
switch (token) {
case SyntaxKind.TemplateTail:
return EndOfLineState.InTemplateMiddleOrTail;
case SyntaxKind.NoSubstitutionTemplateLiteral:
return EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate;
default:
throw Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
}
}
}
return lastOnTemplateStack === SyntaxKind.TemplateHead ? EndOfLineState.InTemplateSubstitutionPosition : undefined;
}
}
function addResult(start: number, end: number, classification: ClassificationType): void {
if (classification === ClassificationType.whiteSpace) {
// Don't bother with whitespace classifications. They're not needed.
return;
}
function pushEncodedClassification(start: number, end: number, offset: number, classification: ClassificationType, result: Push<number>): void {
if (classification === ClassificationType.whiteSpace) {
// Don't bother with whitespace classifications. They're not needed.
return;
}
if (start === 0 && offset > 0) {
// We're classifying the first token, and this was a case where we prepended
// text. We should consider the start of this token to be at the start of
// the original text.
start += offset;
}
if (start === 0 && offset > 0) {
// We're classifying the first token, and this was a case where we prepended text.
// We should consider the start of this token to be at the start of the original text.
start += offset;
}
// All our tokens are in relation to the augmented text. Move them back to be
// relative to the original text.
start -= offset;
end -= offset;
const length = end - start;
const length = end - start;
if (length > 0) {
// All our tokens are in relation to the augmented text. Move them back to be
// relative to the original text.
result.push(start - offset, length, classification);
}
}
if (length > 0) {
result.spans.push(start);
result.spans.push(length);
result.spans.push(classification);
function convertClassificationsToResult(classifications: Classifications, text: string): ClassificationResult {
const entries: ClassificationInfo[] = [];
const dense = classifications.spans;
let lastEnd = 0;
for (let i = 0; i < dense.length; i += 3) {
const start = dense[i];
const length = dense[i + 1];
const type = <ClassificationType>dense[i + 2];
// Make a whitespace entry between the last item and this one.
if (lastEnd >= 0) {
const whitespaceLength = start - lastEnd;
if (whitespaceLength > 0) {
entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace });
}
}
entries.push({ length, classification: convertClassification(type) });
lastEnd = start + length;
}
function isBinaryExpressionOperatorToken(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.AsKeyword:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.AmpersandToken:
case SyntaxKind.CaretToken:
case SyntaxKind.BarToken:
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.BarBarToken:
case SyntaxKind.BarEqualsToken:
case SyntaxKind.AmpersandEqualsToken:
case SyntaxKind.CaretEqualsToken:
case SyntaxKind.LessThanLessThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
case SyntaxKind.PlusEqualsToken:
case SyntaxKind.MinusEqualsToken:
case SyntaxKind.AsteriskEqualsToken:
case SyntaxKind.SlashEqualsToken:
case SyntaxKind.PercentEqualsToken:
case SyntaxKind.EqualsToken:
case SyntaxKind.CommaToken:
return true;
default:
return false;
}
const whitespaceLength = text.length - lastEnd;
if (whitespaceLength > 0) {
entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace });
}
function isPrefixUnaryExpressionOperatorToken(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.TildeToken:
case SyntaxKind.ExclamationToken:
case SyntaxKind.PlusPlusToken:
case SyntaxKind.MinusMinusToken:
return true;
default:
return false;
}
return { entries, finalLexState: classifications.endOfLineState };
}
function convertClassification(type: ClassificationType): TokenClass {
switch (type) {
case ClassificationType.comment: return TokenClass.Comment;
case ClassificationType.keyword: return TokenClass.Keyword;
case ClassificationType.numericLiteral: return TokenClass.NumberLiteral;
case ClassificationType.operator: return TokenClass.Operator;
case ClassificationType.stringLiteral: return TokenClass.StringLiteral;
case ClassificationType.whiteSpace: return TokenClass.Whitespace;
case ClassificationType.punctuation: return TokenClass.Punctuation;
case ClassificationType.identifier:
case ClassificationType.className:
case ClassificationType.enumName:
case ClassificationType.interfaceName:
case ClassificationType.moduleName:
case ClassificationType.typeParameterName:
case ClassificationType.typeAliasName:
case ClassificationType.text:
case ClassificationType.parameterName:
return TokenClass.Identifier;
}
}
/** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */
function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind): boolean {
if (!isAccessibilityModifier(keyword1)) {
// Assume any other keyword combination is legal.
// This can be refined in the future if there are more cases we want the classifier to be better at.
return true;
}
switch (keyword2) {
case SyntaxKind.GetKeyword:
case SyntaxKind.SetKeyword:
case SyntaxKind.ConstructorKeyword:
case SyntaxKind.StaticKeyword:
return true; // Allow things like "public get", "public constructor" and "public static".
default:
return false; // Any other keyword following "public" is actually an identifier, not a real keyword.
}
}
function getPrefixFromLexState(lexState: EndOfLineState): { readonly prefix: string, readonly pushTemplate?: true } {
// If we're in a string literal, then prepend: "\
// (and a newline). That way when we lex we'll think we're still in a string literal.
//
// If we're in a multiline comment, then prepend: /*
// (and a newline). That way when we lex we'll think we're still in a multiline comment.
switch (lexState) {
case EndOfLineState.InDoubleQuoteStringLiteral:
return { prefix: "\"\\\n" };
case EndOfLineState.InSingleQuoteStringLiteral:
return { prefix: "'\\\n" };
case EndOfLineState.InMultiLineCommentTrivia:
return { prefix: "/*\n" };
case EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate:
return { prefix: "`\n" };
case EndOfLineState.InTemplateMiddleOrTail:
return { prefix: "}\n", pushTemplate: true };
case EndOfLineState.InTemplateSubstitutionPosition:
return { prefix: "", pushTemplate: true };
case EndOfLineState.None:
return { prefix: "" };
default:
throw Debug.assertNever(lexState);
}
}
function isBinaryExpressionOperatorToken(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.AsKeyword:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.AmpersandToken:
case SyntaxKind.CaretToken:
case SyntaxKind.BarToken:
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.BarBarToken:
case SyntaxKind.BarEqualsToken:
case SyntaxKind.AmpersandEqualsToken:
case SyntaxKind.CaretEqualsToken:
case SyntaxKind.LessThanLessThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
case SyntaxKind.PlusEqualsToken:
case SyntaxKind.MinusEqualsToken:
case SyntaxKind.AsteriskEqualsToken:
case SyntaxKind.SlashEqualsToken:
case SyntaxKind.PercentEqualsToken:
case SyntaxKind.EqualsToken:
case SyntaxKind.CommaToken:
return true;
default:
return false;
}
}
function isPrefixUnaryExpressionOperatorToken(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.TildeToken:
case SyntaxKind.ExclamationToken:
case SyntaxKind.PlusPlusToken:
case SyntaxKind.MinusMinusToken:
return true;
default:
return false;
}
}
function classFromKind(token: SyntaxKind): ClassificationType {
if (isKeyword(token)) {
return ClassificationType.keyword;
}
else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) {
return ClassificationType.operator;
}
else if (token >= SyntaxKind.FirstPunctuation && token <= SyntaxKind.LastPunctuation) {
return ClassificationType.punctuation;
}
function isKeyword(token: SyntaxKind): boolean {
return token >= SyntaxKind.FirstKeyword && token <= SyntaxKind.LastKeyword;
}
function classFromKind(token: SyntaxKind): ClassificationType {
if (isKeyword(token)) {
return ClassificationType.keyword;
}
else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) {
return ClassificationType.operator;
}
else if (token >= SyntaxKind.FirstPunctuation && token <= SyntaxKind.LastPunctuation) {
return ClassificationType.punctuation;
}
switch (token) {
case SyntaxKind.NumericLiteral:
return ClassificationType.numericLiteral;
case SyntaxKind.StringLiteral:
switch (token) {
case SyntaxKind.NumericLiteral:
return ClassificationType.numericLiteral;
case SyntaxKind.StringLiteral:
return ClassificationType.stringLiteral;
case SyntaxKind.RegularExpressionLiteral:
return ClassificationType.regularExpressionLiteral;
case SyntaxKind.ConflictMarkerTrivia:
case SyntaxKind.MultiLineCommentTrivia:
case SyntaxKind.SingleLineCommentTrivia:
return ClassificationType.comment;
case SyntaxKind.WhitespaceTrivia:
case SyntaxKind.NewLineTrivia:
return ClassificationType.whiteSpace;
case SyntaxKind.Identifier:
default:
if (isTemplateLiteralKind(token)) {
return ClassificationType.stringLiteral;
case SyntaxKind.RegularExpressionLiteral:
return ClassificationType.regularExpressionLiteral;
case SyntaxKind.ConflictMarkerTrivia:
case SyntaxKind.MultiLineCommentTrivia:
case SyntaxKind.SingleLineCommentTrivia:
return ClassificationType.comment;
case SyntaxKind.WhitespaceTrivia:
case SyntaxKind.NewLineTrivia:
return ClassificationType.whiteSpace;
case SyntaxKind.Identifier:
default:
if (isTemplateLiteralKind(token)) {
return ClassificationType.stringLiteral;
}
return ClassificationType.identifier;
}
}
return ClassificationType.identifier;
}
return {
getClassificationsForLine,
getEncodedLexicalClassifications
};
}
/* @internal */
export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap<true>, span: TextSpan): ClassifiedSpan[] {
return convertClassifications(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span));
return convertClassificationsToSpans(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span));
}
function checkForClassificationCancellation(cancellationToken: CancellationToken, kind: SyntaxKind) {
@@ -583,7 +562,7 @@ namespace ts {
}
}
function convertClassifications(classifications: Classifications): ClassifiedSpan[] {
function convertClassificationsToSpans(classifications: Classifications): ClassifiedSpan[] {
Debug.assert(classifications.spans.length % 3 === 0);
const dense = classifications.spans;
const result: ClassifiedSpan[] = [];
@@ -599,7 +578,7 @@ namespace ts {
/* @internal */
export function getSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): ClassifiedSpan[] {
return convertClassifications(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span));
return convertClassificationsToSpans(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span));
}
/* @internal */
+6 -1
View File
@@ -461,6 +461,7 @@ declare namespace ts {
}
type DotDotDotToken = Token<SyntaxKind.DotDotDotToken>;
type QuestionToken = Token<SyntaxKind.QuestionToken>;
type ExclamationToken = Token<SyntaxKind.ExclamationToken>;
type ColonToken = Token<SyntaxKind.ColonToken>;
type EqualsToken = Token<SyntaxKind.EqualsToken>;
type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
@@ -537,6 +538,7 @@ declare namespace ts {
kind: SyntaxKind.VariableDeclaration;
parent?: VariableDeclarationList | CatchClause;
name: BindingName;
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression;
}
@@ -571,8 +573,9 @@ declare namespace ts {
}
interface PropertyDeclaration extends ClassElement, JSDocContainer {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken;
name: PropertyName;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression;
}
@@ -606,6 +609,7 @@ declare namespace ts {
dotDotDotToken?: DotDotDotToken;
name: DeclarationName;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression;
}
@@ -2287,6 +2291,7 @@ declare namespace ts {
strict?: boolean;
strictFunctionTypes?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
+6 -1
View File
@@ -461,6 +461,7 @@ declare namespace ts {
}
type DotDotDotToken = Token<SyntaxKind.DotDotDotToken>;
type QuestionToken = Token<SyntaxKind.QuestionToken>;
type ExclamationToken = Token<SyntaxKind.ExclamationToken>;
type ColonToken = Token<SyntaxKind.ColonToken>;
type EqualsToken = Token<SyntaxKind.EqualsToken>;
type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
@@ -537,6 +538,7 @@ declare namespace ts {
kind: SyntaxKind.VariableDeclaration;
parent?: VariableDeclarationList | CatchClause;
name: BindingName;
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression;
}
@@ -571,8 +573,9 @@ declare namespace ts {
}
interface PropertyDeclaration extends ClassElement, JSDocContainer {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken;
name: PropertyName;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression;
}
@@ -606,6 +609,7 @@ declare namespace ts {
dotDotDotToken?: DotDotDotToken;
name: DeclarationName;
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
type?: TypeNode;
initializer?: Expression;
}
@@ -2287,6 +2291,7 @@ declare namespace ts {
strict?: boolean;
strictFunctionTypes?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
@@ -0,0 +1,113 @@
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(5,5): error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(20,6): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(21,6): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(22,13): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(28,6): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(34,15): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(68,10): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(69,10): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(70,10): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(75,15): error TS1255: A definite assignment assertion '!' is not permitted in this context.
tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts(76,15): error TS1255: A definite assignment assertion '!' is not permitted in this context.
==== tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts (11 errors) ====
// Suppress strict property initialization check
class C1 {
a!: number;
b: string; // Error
~
!!! error TS2564: Property 'b' has no initializer and is not definitely assigned in the constructor.
}
// Suppress definite assignment check in constructor
class C2 {
a!: number;
constructor() {
let x = this.a;
}
}
// Definite assignment assertion requires type annotation, no initializer, no static modifier
class C3 {
a! = 1;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
b!: number = 1;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
static c!: number;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
}
// Definite assignment assertion not permitted in ambient context
declare class C4 {
a!: number;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
}
// Definite assignment assertion not permitted on abstract property
abstract class C5 {
abstract a!: number;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
}
// Suppress definite assignment check for variable
function f1() {
let x!: number;
let y = x;
var a!: number;
var b = a;
}
function f2() {
let x!: string | number;
if (typeof x === "string") {
let s: string = x;
}
else {
let n: number = x;
}
}
function f3() {
let x!: number;
const g = () => {
x = 1;
}
g();
let y = x;
}
// Definite assignment assertion requires type annotation and no initializer
function f4() {
let a!;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
let b! = 1;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
let c!: number = 1;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
}
// Definite assignment assertion not permitted in ambient context
declare let v1!: number;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
declare var v2!: number;
~
!!! error TS1255: A definite assignment assertion '!' is not permitted in this context.
@@ -0,0 +1,166 @@
//// [definiteAssignmentAssertions.ts]
// Suppress strict property initialization check
class C1 {
a!: number;
b: string; // Error
}
// Suppress definite assignment check in constructor
class C2 {
a!: number;
constructor() {
let x = this.a;
}
}
// Definite assignment assertion requires type annotation, no initializer, no static modifier
class C3 {
a! = 1;
b!: number = 1;
static c!: number;
}
// Definite assignment assertion not permitted in ambient context
declare class C4 {
a!: number;
}
// Definite assignment assertion not permitted on abstract property
abstract class C5 {
abstract a!: number;
}
// Suppress definite assignment check for variable
function f1() {
let x!: number;
let y = x;
var a!: number;
var b = a;
}
function f2() {
let x!: string | number;
if (typeof x === "string") {
let s: string = x;
}
else {
let n: number = x;
}
}
function f3() {
let x!: number;
const g = () => {
x = 1;
}
g();
let y = x;
}
// Definite assignment assertion requires type annotation and no initializer
function f4() {
let a!;
let b! = 1;
let c!: number = 1;
}
// Definite assignment assertion not permitted in ambient context
declare let v1!: number;
declare var v2!: number;
//// [definiteAssignmentAssertions.js]
"use strict";
// Suppress strict property initialization check
var C1 = /** @class */ (function () {
function C1() {
}
return C1;
}());
// Suppress definite assignment check in constructor
var C2 = /** @class */ (function () {
function C2() {
var x = this.a;
}
return C2;
}());
// Definite assignment assertion requires type annotation, no initializer, no static modifier
var C3 = /** @class */ (function () {
function C3() {
this.a = 1;
this.b = 1;
}
return C3;
}());
// Definite assignment assertion not permitted on abstract property
var C5 = /** @class */ (function () {
function C5() {
}
return C5;
}());
// Suppress definite assignment check for variable
function f1() {
var x;
var y = x;
var a;
var b = a;
}
function f2() {
var x;
if (typeof x === "string") {
var s = x;
}
else {
var n = x;
}
}
function f3() {
var x;
var g = function () {
x = 1;
};
g();
var y = x;
}
// Definite assignment assertion requires type annotation and no initializer
function f4() {
var a;
var b = 1;
var c = 1;
}
//// [definiteAssignmentAssertions.d.ts]
declare class C1 {
a: number;
b: string;
}
declare class C2 {
a: number;
constructor();
}
declare class C3 {
a: number;
b: number;
static c: number;
}
declare class C4 {
a: number;
}
declare abstract class C5 {
abstract a: number;
}
declare function f1(): void;
declare function f2(): void;
declare function f3(): void;
declare function f4(): void;
declare let v1: number;
declare var v2: number;
@@ -0,0 +1,146 @@
=== tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts ===
// Suppress strict property initialization check
class C1 {
>C1 : Symbol(C1, Decl(definiteAssignmentAssertions.ts, 0, 0))
a!: number;
>a : Symbol(C1.a, Decl(definiteAssignmentAssertions.ts, 2, 10))
b: string; // Error
>b : Symbol(C1.b, Decl(definiteAssignmentAssertions.ts, 3, 15))
}
// Suppress definite assignment check in constructor
class C2 {
>C2 : Symbol(C2, Decl(definiteAssignmentAssertions.ts, 5, 1))
a!: number;
>a : Symbol(C2.a, Decl(definiteAssignmentAssertions.ts, 9, 10))
constructor() {
let x = this.a;
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 12, 11))
>this.a : Symbol(C2.a, Decl(definiteAssignmentAssertions.ts, 9, 10))
>this : Symbol(C2, Decl(definiteAssignmentAssertions.ts, 5, 1))
>a : Symbol(C2.a, Decl(definiteAssignmentAssertions.ts, 9, 10))
}
}
// Definite assignment assertion requires type annotation, no initializer, no static modifier
class C3 {
>C3 : Symbol(C3, Decl(definiteAssignmentAssertions.ts, 14, 1))
a! = 1;
>a : Symbol(C3.a, Decl(definiteAssignmentAssertions.ts, 18, 10))
b!: number = 1;
>b : Symbol(C3.b, Decl(definiteAssignmentAssertions.ts, 19, 11))
static c!: number;
>c : Symbol(C3.c, Decl(definiteAssignmentAssertions.ts, 20, 19))
}
// Definite assignment assertion not permitted in ambient context
declare class C4 {
>C4 : Symbol(C4, Decl(definiteAssignmentAssertions.ts, 22, 1))
a!: number;
>a : Symbol(C4.a, Decl(definiteAssignmentAssertions.ts, 26, 18))
}
// Definite assignment assertion not permitted on abstract property
abstract class C5 {
>C5 : Symbol(C5, Decl(definiteAssignmentAssertions.ts, 28, 1))
abstract a!: number;
>a : Symbol(C5.a, Decl(definiteAssignmentAssertions.ts, 32, 19))
}
// Suppress definite assignment check for variable
function f1() {
>f1 : Symbol(f1, Decl(definiteAssignmentAssertions.ts, 34, 1))
let x!: number;
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 39, 7))
let y = x;
>y : Symbol(y, Decl(definiteAssignmentAssertions.ts, 40, 7))
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 39, 7))
var a!: number;
>a : Symbol(a, Decl(definiteAssignmentAssertions.ts, 41, 7))
var b = a;
>b : Symbol(b, Decl(definiteAssignmentAssertions.ts, 42, 7))
>a : Symbol(a, Decl(definiteAssignmentAssertions.ts, 41, 7))
}
function f2() {
>f2 : Symbol(f2, Decl(definiteAssignmentAssertions.ts, 43, 1))
let x!: string | number;
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
if (typeof x === "string") {
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
let s: string = x;
>s : Symbol(s, Decl(definiteAssignmentAssertions.ts, 48, 11))
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
}
else {
let n: number = x;
>n : Symbol(n, Decl(definiteAssignmentAssertions.ts, 51, 11))
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 46, 7))
}
}
function f3() {
>f3 : Symbol(f3, Decl(definiteAssignmentAssertions.ts, 53, 1))
let x!: number;
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 56, 7))
const g = () => {
>g : Symbol(g, Decl(definiteAssignmentAssertions.ts, 57, 9))
x = 1;
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 56, 7))
}
g();
>g : Symbol(g, Decl(definiteAssignmentAssertions.ts, 57, 9))
let y = x;
>y : Symbol(y, Decl(definiteAssignmentAssertions.ts, 61, 7))
>x : Symbol(x, Decl(definiteAssignmentAssertions.ts, 56, 7))
}
// Definite assignment assertion requires type annotation and no initializer
function f4() {
>f4 : Symbol(f4, Decl(definiteAssignmentAssertions.ts, 62, 1))
let a!;
>a : Symbol(a, Decl(definiteAssignmentAssertions.ts, 67, 7))
let b! = 1;
>b : Symbol(b, Decl(definiteAssignmentAssertions.ts, 68, 7))
let c!: number = 1;
>c : Symbol(c, Decl(definiteAssignmentAssertions.ts, 69, 7))
}
// Definite assignment assertion not permitted in ambient context
declare let v1!: number;
>v1 : Symbol(v1, Decl(definiteAssignmentAssertions.ts, 74, 11))
declare var v2!: number;
>v2 : Symbol(v2, Decl(definiteAssignmentAssertions.ts, 75, 11))
@@ -0,0 +1,157 @@
=== tests/cases/conformance/controlFlow/definiteAssignmentAssertions.ts ===
// Suppress strict property initialization check
class C1 {
>C1 : C1
a!: number;
>a : number
b: string; // Error
>b : string
}
// Suppress definite assignment check in constructor
class C2 {
>C2 : C2
a!: number;
>a : number
constructor() {
let x = this.a;
>x : number
>this.a : number
>this : this
>a : number
}
}
// Definite assignment assertion requires type annotation, no initializer, no static modifier
class C3 {
>C3 : C3
a! = 1;
>a : number
>1 : 1
b!: number = 1;
>b : number
>1 : 1
static c!: number;
>c : number
}
// Definite assignment assertion not permitted in ambient context
declare class C4 {
>C4 : C4
a!: number;
>a : number
}
// Definite assignment assertion not permitted on abstract property
abstract class C5 {
>C5 : C5
abstract a!: number;
>a : number
}
// Suppress definite assignment check for variable
function f1() {
>f1 : () => void
let x!: number;
>x : number
let y = x;
>y : number
>x : number
var a!: number;
>a : number
var b = a;
>b : number
>a : number
}
function f2() {
>f2 : () => void
let x!: string | number;
>x : string | number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : string | number
>"string" : "string"
let s: string = x;
>s : string
>x : string
}
else {
let n: number = x;
>n : number
>x : number
}
}
function f3() {
>f3 : () => void
let x!: number;
>x : number
const g = () => {
>g : () => void
>() => { x = 1; } : () => void
x = 1;
>x = 1 : 1
>x : number
>1 : 1
}
g();
>g() : void
>g : () => void
let y = x;
>y : number
>x : number
}
// Definite assignment assertion requires type annotation and no initializer
function f4() {
>f4 : () => void
let a!;
>a : any
let b! = 1;
>b : number
>1 : 1
let c!: number = 1;
>c : number
>1 : 1
}
// Definite assignment assertion not permitted in ambient context
declare let v1!: number;
>v1 : number
declare var v2!: number;
>v2 : number
@@ -10,7 +10,7 @@ type Data<T> = {
};
class Parent<M> {
private data: Data<M>;
constructor(private data: Data<M>) {}
getData(): Data<M> {
return this.data;
}
@@ -50,7 +50,8 @@ var __extends = (this && this.__extends) || (function () {
})();
exports.__esModule = true;
var Parent = /** @class */ (function () {
function Parent() {
function Parent(data) {
this.data = data;
}
Parent.prototype.getData = function () {
return this.data;
@@ -29,20 +29,20 @@ class Parent<M> {
>Parent : Symbol(Parent, Decl(indexedAccessTypeConstraints.ts, 8, 2))
>M : Symbol(M, Decl(indexedAccessTypeConstraints.ts, 10, 13))
private data: Data<M>;
>data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 10, 17))
constructor(private data: Data<M>) {}
>data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 11, 16))
>Data : Symbol(Data, Decl(indexedAccessTypeConstraints.ts, 4, 1))
>M : Symbol(M, Decl(indexedAccessTypeConstraints.ts, 10, 13))
getData(): Data<M> {
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 26))
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 41))
>Data : Symbol(Data, Decl(indexedAccessTypeConstraints.ts, 4, 1))
>M : Symbol(M, Decl(indexedAccessTypeConstraints.ts, 10, 13))
return this.data;
>this.data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 10, 17))
>this.data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 11, 16))
>this : Symbol(Parent, Decl(indexedAccessTypeConstraints.ts, 8, 2))
>data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 10, 17))
>data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 11, 16))
}
}
@@ -59,9 +59,9 @@ export class Foo<C> extends Parent<IData<C>> {
return this.getData().get('content');
>this.getData().get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 6, 16))
>this.getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 26))
>this.getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 41))
>this : Symbol(Foo, Decl(indexedAccessTypeConstraints.ts, 15, 1))
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 26))
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 41))
>get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 6, 16))
}
}
@@ -81,9 +81,9 @@ export class Bar<C, T extends IData<C>> extends Parent<T> {
return this.getData().get('content');
>this.getData().get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 6, 16))
>this.getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 26))
>this.getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 41))
>this : Symbol(Bar, Decl(indexedAccessTypeConstraints.ts, 21, 1))
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 26))
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 11, 41))
>get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 6, 16))
}
}
@@ -29,7 +29,7 @@ class Parent<M> {
>Parent : Parent<M>
>M : M
private data: Data<M>;
constructor(private data: Data<M>) {}
>data : { get: <K extends keyof M>(prop: K) => M[K]; }
>Data : { get: <K extends keyof T>(prop: K) => T[K]; }
>M : M
@@ -1,8 +1,7 @@
/a.js(2,14): error TS8021: JSDoc '@typedef' tag should either have a type annotation or be followed by '@property' or '@member' tags.
/a.js(12,11): error TS1005: '{' expected.
==== /a.js (2 errors) ====
==== /a.js (1 errors) ====
// Bad: missing a type
/** @typedef T */
~
@@ -17,7 +16,5 @@
*/
/** @type Person */
~~~~~~
!!! error TS1005: '{' expected.
const person = { name: "" };
@@ -14,8 +14,8 @@ const t = 0;
/** @type Person */
const person = { name: "" };
>person : { [x: string]: any; name: string; }
>{ name: "" } : { [x: string]: any; name: string; }
>person : { name: string; }
>{ name: "" } : { name: string; }
>name : string
>"" : ""
@@ -5,7 +5,7 @@
* @type Function
*/
var isArray = Array.isArray;
>isArray : (arg: any) => arg is any[]
>isArray : Function
>Array.isArray : (arg: any) => arg is any[]
>Array : ArrayConstructor
>isArray : (arg: any) => arg is any[]
@@ -1,9 +1,9 @@
=== tests/cases/compiler/modularizeLibrary_Dom.iterable.ts ===
for (const element of document.getElementsByTagName("a")) {
>element : Symbol(element, Decl(modularizeLibrary_Dom.iterable.ts, 0, 10))
>document.getElementsByTagName : Symbol(Document.getElementsByTagName, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>document.getElementsByTagName : Symbol(Document.getElementsByTagName, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>document : Symbol(document, Decl(lib.dom.d.ts, --, --))
>getElementsByTagName : Symbol(Document.getElementsByTagName, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>getElementsByTagName : Symbol(Document.getElementsByTagName, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
element.href;
>element.href : Symbol(HTMLAnchorElement.href, Decl(lib.dom.d.ts, --, --))
@@ -2,9 +2,9 @@
for (const element of document.getElementsByTagName("a")) {
>element : HTMLAnchorElement
>document.getElementsByTagName("a") : NodeListOf<HTMLAnchorElement>
>document.getElementsByTagName : { <K extends "symbol" | "object" | "abbr" | "acronym" | "address" | "article" | "aside" | "b" | "bdo" | "big" | "center" | "circle" | "cite" | "clippath" | "code" | "dd" | "defs" | "desc" | "dfn" | "dt" | "ellipse" | "em" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "figcaption" | "figure" | "filter" | "footer" | "foreignobject" | "g" | "header" | "hgroup" | "i" | "image" | "kbd" | "keygen" | "line" | "lineargradient" | "mark" | "marker" | "mask" | "metadata" | "nav" | "nobr" | "noframes" | "noscript" | "path" | "pattern" | "plaintext" | "polygon" | "polyline" | "radialgradient" | "rect" | "rt" | "ruby" | "s" | "samp" | "section" | "small" | "stop" | "strike" | "strong" | "sub" | "sup" | "svg" | "switch" | "text" | "textpath" | "tspan" | "tt" | "u" | "use" | "var" | "view" | "wbr" | "a" | "applet" | "area" | "audio" | "base" | "basefont" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "col" | "colgroup" | "data" | "datalist" | "del" | "dir" | "div" | "dl" | "embed" | "fieldset" | "font" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "hr" | "html" | "iframe" | "img" | "input" | "ins" | "isindex" | "label" | "legend" | "li" | "link" | "listing" | "map" | "marquee" | "menu" | "meta" | "meter" | "nextid" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "pre" | "progress" | "q" | "script" | "select" | "source" | "span" | "style" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "ul" | "video" | "x-ms-webview" | "xmp">(tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf<Element>; }
>document.getElementsByTagName : { <K extends "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "dfn" | "dir" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "font" | "footer" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "listing" | "map" | "mark" | "marquee" | "menu" | "meta" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "plaintext" | "pre" | "progress" | "q" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "small" | "source" | "span" | "strike" | "strong" | "style" | "sub" | "sup" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tt" | "u" | "ul" | "var" | "video" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): NodeListOf<HTMLElementTagNameMap[K]>; <K extends "symbol" | "circle" | "clippath" | "defs" | "desc" | "ellipse" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "filter" | "foreignobject" | "g" | "image" | "line" | "lineargradient" | "marker" | "mask" | "metadata" | "path" | "pattern" | "polygon" | "polyline" | "radialgradient" | "rect" | "stop" | "svg" | "switch" | "text" | "textpath" | "tspan" | "use" | "view">(tagname: K): NodeListOf<SVGElementTagNameMap[K]>; (tagname: string): NodeListOf<Element>; }
>document : Document
>getElementsByTagName : { <K extends "symbol" | "object" | "abbr" | "acronym" | "address" | "article" | "aside" | "b" | "bdo" | "big" | "center" | "circle" | "cite" | "clippath" | "code" | "dd" | "defs" | "desc" | "dfn" | "dt" | "ellipse" | "em" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "figcaption" | "figure" | "filter" | "footer" | "foreignobject" | "g" | "header" | "hgroup" | "i" | "image" | "kbd" | "keygen" | "line" | "lineargradient" | "mark" | "marker" | "mask" | "metadata" | "nav" | "nobr" | "noframes" | "noscript" | "path" | "pattern" | "plaintext" | "polygon" | "polyline" | "radialgradient" | "rect" | "rt" | "ruby" | "s" | "samp" | "section" | "small" | "stop" | "strike" | "strong" | "sub" | "sup" | "svg" | "switch" | "text" | "textpath" | "tspan" | "tt" | "u" | "use" | "var" | "view" | "wbr" | "a" | "applet" | "area" | "audio" | "base" | "basefont" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "col" | "colgroup" | "data" | "datalist" | "del" | "dir" | "div" | "dl" | "embed" | "fieldset" | "font" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "hr" | "html" | "iframe" | "img" | "input" | "ins" | "isindex" | "label" | "legend" | "li" | "link" | "listing" | "map" | "marquee" | "menu" | "meta" | "meter" | "nextid" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "pre" | "progress" | "q" | "script" | "select" | "source" | "span" | "style" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "ul" | "video" | "x-ms-webview" | "xmp">(tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf<Element>; }
>getElementsByTagName : { <K extends "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "dfn" | "dir" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "font" | "footer" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "listing" | "map" | "mark" | "marquee" | "menu" | "meta" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "plaintext" | "pre" | "progress" | "q" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "small" | "source" | "span" | "strike" | "strong" | "style" | "sub" | "sup" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tt" | "u" | "ul" | "var" | "video" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): NodeListOf<HTMLElementTagNameMap[K]>; <K extends "symbol" | "circle" | "clippath" | "defs" | "desc" | "ellipse" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "filter" | "foreignobject" | "g" | "image" | "line" | "lineargradient" | "marker" | "mask" | "metadata" | "path" | "pattern" | "polygon" | "polyline" | "radialgradient" | "rect" | "stop" | "svg" | "switch" | "text" | "textpath" | "tspan" | "use" | "view">(tagname: K): NodeListOf<SVGElementTagNameMap[K]>; (tagname: string): NodeListOf<Element>; }
>"a" : "a"
element.href;
@@ -0,0 +1,79 @@
//// [narrowingConstrainedTypeVariable.ts]
// Repro from #20138
class C { }
function f1<T extends C>(v: T | string): void {
if (v instanceof C) {
const x: T = v;
}
else {
const s: string = v;
}
}
class D { }
function f2<T extends C, U extends D>(v: T | U) {
if (v instanceof C) {
const x: T = v;
}
else {
const y: U = v;
}
}
class E { x: string | undefined }
function f3<T extends E>(v: T | { x: string }) {
if (v instanceof E) {
const x: T = v;
}
else {
const y: { x: string } = v;
}
}
//// [narrowingConstrainedTypeVariable.js]
"use strict";
// Repro from #20138
var C = /** @class */ (function () {
function C() {
}
return C;
}());
function f1(v) {
if (v instanceof C) {
var x = v;
}
else {
var s = v;
}
}
var D = /** @class */ (function () {
function D() {
}
return D;
}());
function f2(v) {
if (v instanceof C) {
var x = v;
}
else {
var y = v;
}
}
var E = /** @class */ (function () {
function E() {
}
return E;
}());
function f3(v) {
if (v instanceof E) {
var x = v;
}
else {
var y = v;
}
}
@@ -0,0 +1,88 @@
=== tests/cases/conformance/types/typeRelationships/instanceOf/narrowingConstrainedTypeVariable.ts ===
// Repro from #20138
class C { }
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
function f1<T extends C>(v: T | string): void {
>f1 : Symbol(f1, Decl(narrowingConstrainedTypeVariable.ts, 2, 11))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 4, 12))
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 4, 12))
if (v instanceof C) {
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
const x: T = v;
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 6, 13))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 4, 12))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
}
else {
const s: string = v;
>s : Symbol(s, Decl(narrowingConstrainedTypeVariable.ts, 9, 13))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
}
}
class D { }
>D : Symbol(D, Decl(narrowingConstrainedTypeVariable.ts, 11, 1))
function f2<T extends C, U extends D>(v: T | U) {
>f2 : Symbol(f2, Decl(narrowingConstrainedTypeVariable.ts, 13, 11))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 15, 12))
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
>U : Symbol(U, Decl(narrowingConstrainedTypeVariable.ts, 15, 24))
>D : Symbol(D, Decl(narrowingConstrainedTypeVariable.ts, 11, 1))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 15, 12))
>U : Symbol(U, Decl(narrowingConstrainedTypeVariable.ts, 15, 24))
if (v instanceof C) {
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
const x: T = v;
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 17, 13))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 15, 12))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
}
else {
const y: U = v;
>y : Symbol(y, Decl(narrowingConstrainedTypeVariable.ts, 20, 13))
>U : Symbol(U, Decl(narrowingConstrainedTypeVariable.ts, 15, 24))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
}
}
class E { x: string | undefined }
>E : Symbol(E, Decl(narrowingConstrainedTypeVariable.ts, 22, 1))
>x : Symbol(E.x, Decl(narrowingConstrainedTypeVariable.ts, 24, 9))
function f3<T extends E>(v: T | { x: string }) {
>f3 : Symbol(f3, Decl(narrowingConstrainedTypeVariable.ts, 24, 33))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 26, 12))
>E : Symbol(E, Decl(narrowingConstrainedTypeVariable.ts, 22, 1))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 26, 12))
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 26, 33))
if (v instanceof E) {
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
>E : Symbol(E, Decl(narrowingConstrainedTypeVariable.ts, 22, 1))
const x: T = v;
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 28, 13))
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 26, 12))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
}
else {
const y: { x: string } = v;
>y : Symbol(y, Decl(narrowingConstrainedTypeVariable.ts, 31, 13))
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 31, 18))
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
}
}
@@ -0,0 +1,91 @@
=== tests/cases/conformance/types/typeRelationships/instanceOf/narrowingConstrainedTypeVariable.ts ===
// Repro from #20138
class C { }
>C : C
function f1<T extends C>(v: T | string): void {
>f1 : <T extends C>(v: string | T) => void
>T : T
>C : C
>v : string | T
>T : T
if (v instanceof C) {
>v instanceof C : boolean
>v : string | T
>C : typeof C
const x: T = v;
>x : T
>T : T
>v : T
}
else {
const s: string = v;
>s : string
>v : string
}
}
class D { }
>D : D
function f2<T extends C, U extends D>(v: T | U) {
>f2 : <T extends C, U extends D>(v: T | U) => void
>T : T
>C : C
>U : U
>D : D
>v : T | U
>T : T
>U : U
if (v instanceof C) {
>v instanceof C : boolean
>v : T | U
>C : typeof C
const x: T = v;
>x : T
>T : T
>v : T
}
else {
const y: U = v;
>y : U
>U : U
>v : U
}
}
class E { x: string | undefined }
>E : E
>x : string | undefined
function f3<T extends E>(v: T | { x: string }) {
>f3 : <T extends E>(v: T | { x: string; }) => void
>T : T
>E : E
>v : T | { x: string; }
>T : T
>x : string
if (v instanceof E) {
>v instanceof E : boolean
>v : T | { x: string; }
>E : typeof E
const x: T = v;
>x : T
>T : T
>v : T
}
else {
const y: { x: string } = v;
>y : { x: string; }
>x : string
>v : { x: string; }
}
}
@@ -0,0 +1,120 @@
tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts(4,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts(6,5): error TS2564: Property 'c' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts(48,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts(71,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts(93,22): error TS2565: Property 'a' is used before being assigned.
tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts(94,23): error TS2565: Property 'b' is used before being assigned.
==== tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts (6 errors) ====
// Properties with non-undefined types require initialization
class C1 {
a: number; // Error
~
!!! error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
b: number | undefined;
c: number | null; // Error
~
!!! error TS2564: Property 'c' has no initializer and is not definitely assigned in the constructor.
d?: number;
}
// No strict initialization checks in ambient contexts
declare class C2 {
a: number;
b: number | undefined;
c: number | null;
d?: number;
}
// No strict initialization checks for static members
class C3 {
static a: number;
static b: number | undefined;
static c: number | null;
static d?: number;
}
// Initializer satisfies strict initialization check
class C4 {
a = 0;
b: number = 0;
c: string = "abc";
}
// Assignment in constructor satisfies strict initialization check
class C5 {
a: number;
constructor() {
this.a = 0;
}
}
// All code paths must contain assignment
class C6 {
a: number; // Error
~
!!! error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
constructor(cond: boolean) {
if (cond) {
return;
}
this.a = 0;
}
}
class C7 {
a: number;
constructor(cond: boolean) {
if (cond) {
this.a = 1;
return;
}
this.a = 0;
}
}
// Properties with string literal names aren't checked
class C8 {
a: number; // Error
~
!!! error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
"b": number;
0: number;
}
// No strict initialization checks for abstract members
abstract class C9 {
abstract a: number;
abstract b: number | undefined;
abstract c: number | null;
abstract d?: number;
}
// Properties with non-undefined types must be assigned before they can be accessed
// within their constructor
class C10 {
a: number;
b: number;
c?: number;
constructor() {
let x = this.a; // Error
~
!!! error TS2565: Property 'a' is used before being assigned.
this.a = this.b; // Error
~
!!! error TS2565: Property 'b' is used before being assigned.
this.b = x;
let y = this.c;
}
}
@@ -0,0 +1,229 @@
//// [strictPropertyInitialization.ts]
// Properties with non-undefined types require initialization
class C1 {
a: number; // Error
b: number | undefined;
c: number | null; // Error
d?: number;
}
// No strict initialization checks in ambient contexts
declare class C2 {
a: number;
b: number | undefined;
c: number | null;
d?: number;
}
// No strict initialization checks for static members
class C3 {
static a: number;
static b: number | undefined;
static c: number | null;
static d?: number;
}
// Initializer satisfies strict initialization check
class C4 {
a = 0;
b: number = 0;
c: string = "abc";
}
// Assignment in constructor satisfies strict initialization check
class C5 {
a: number;
constructor() {
this.a = 0;
}
}
// All code paths must contain assignment
class C6 {
a: number; // Error
constructor(cond: boolean) {
if (cond) {
return;
}
this.a = 0;
}
}
class C7 {
a: number;
constructor(cond: boolean) {
if (cond) {
this.a = 1;
return;
}
this.a = 0;
}
}
// Properties with string literal names aren't checked
class C8 {
a: number; // Error
"b": number;
0: number;
}
// No strict initialization checks for abstract members
abstract class C9 {
abstract a: number;
abstract b: number | undefined;
abstract c: number | null;
abstract d?: number;
}
// Properties with non-undefined types must be assigned before they can be accessed
// within their constructor
class C10 {
a: number;
b: number;
c?: number;
constructor() {
let x = this.a; // Error
this.a = this.b; // Error
this.b = x;
let y = this.c;
}
}
//// [strictPropertyInitialization.js]
"use strict";
// Properties with non-undefined types require initialization
var C1 = /** @class */ (function () {
function C1() {
}
return C1;
}());
// No strict initialization checks for static members
var C3 = /** @class */ (function () {
function C3() {
}
return C3;
}());
// Initializer satisfies strict initialization check
var C4 = /** @class */ (function () {
function C4() {
this.a = 0;
this.b = 0;
this.c = "abc";
}
return C4;
}());
// Assignment in constructor satisfies strict initialization check
var C5 = /** @class */ (function () {
function C5() {
this.a = 0;
}
return C5;
}());
// All code paths must contain assignment
var C6 = /** @class */ (function () {
function C6(cond) {
if (cond) {
return;
}
this.a = 0;
}
return C6;
}());
var C7 = /** @class */ (function () {
function C7(cond) {
if (cond) {
this.a = 1;
return;
}
this.a = 0;
}
return C7;
}());
// Properties with string literal names aren't checked
var C8 = /** @class */ (function () {
function C8() {
}
return C8;
}());
// No strict initialization checks for abstract members
var C9 = /** @class */ (function () {
function C9() {
}
return C9;
}());
// Properties with non-undefined types must be assigned before they can be accessed
// within their constructor
var C10 = /** @class */ (function () {
function C10() {
var x = this.a; // Error
this.a = this.b; // Error
this.b = x;
var y = this.c;
}
return C10;
}());
//// [strictPropertyInitialization.d.ts]
declare class C1 {
a: number;
b: number | undefined;
c: number | null;
d?: number;
}
declare class C2 {
a: number;
b: number | undefined;
c: number | null;
d?: number;
}
declare class C3 {
static a: number;
static b: number | undefined;
static c: number | null;
static d?: number;
}
declare class C4 {
a: number;
b: number;
c: string;
}
declare class C5 {
a: number;
constructor();
}
declare class C6 {
a: number;
constructor(cond: boolean);
}
declare class C7 {
a: number;
constructor(cond: boolean);
}
declare class C8 {
a: number;
"b": number;
0: number;
}
declare abstract class C9 {
abstract a: number;
abstract b: number | undefined;
abstract c: number | null;
abstract d?: number;
}
declare class C10 {
a: number;
b: number;
c?: number;
constructor();
}
@@ -0,0 +1,209 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts ===
// Properties with non-undefined types require initialization
class C1 {
>C1 : Symbol(C1, Decl(strictPropertyInitialization.ts, 0, 0))
a: number; // Error
>a : Symbol(C1.a, Decl(strictPropertyInitialization.ts, 2, 10))
b: number | undefined;
>b : Symbol(C1.b, Decl(strictPropertyInitialization.ts, 3, 14))
c: number | null; // Error
>c : Symbol(C1.c, Decl(strictPropertyInitialization.ts, 4, 26))
d?: number;
>d : Symbol(C1.d, Decl(strictPropertyInitialization.ts, 5, 21))
}
// No strict initialization checks in ambient contexts
declare class C2 {
>C2 : Symbol(C2, Decl(strictPropertyInitialization.ts, 7, 1))
a: number;
>a : Symbol(C2.a, Decl(strictPropertyInitialization.ts, 11, 18))
b: number | undefined;
>b : Symbol(C2.b, Decl(strictPropertyInitialization.ts, 12, 14))
c: number | null;
>c : Symbol(C2.c, Decl(strictPropertyInitialization.ts, 13, 26))
d?: number;
>d : Symbol(C2.d, Decl(strictPropertyInitialization.ts, 14, 21))
}
// No strict initialization checks for static members
class C3 {
>C3 : Symbol(C3, Decl(strictPropertyInitialization.ts, 16, 1))
static a: number;
>a : Symbol(C3.a, Decl(strictPropertyInitialization.ts, 20, 10))
static b: number | undefined;
>b : Symbol(C3.b, Decl(strictPropertyInitialization.ts, 21, 21))
static c: number | null;
>c : Symbol(C3.c, Decl(strictPropertyInitialization.ts, 22, 33))
static d?: number;
>d : Symbol(C3.d, Decl(strictPropertyInitialization.ts, 23, 28))
}
// Initializer satisfies strict initialization check
class C4 {
>C4 : Symbol(C4, Decl(strictPropertyInitialization.ts, 25, 1))
a = 0;
>a : Symbol(C4.a, Decl(strictPropertyInitialization.ts, 29, 10))
b: number = 0;
>b : Symbol(C4.b, Decl(strictPropertyInitialization.ts, 30, 10))
c: string = "abc";
>c : Symbol(C4.c, Decl(strictPropertyInitialization.ts, 31, 18))
}
// Assignment in constructor satisfies strict initialization check
class C5 {
>C5 : Symbol(C5, Decl(strictPropertyInitialization.ts, 33, 1))
a: number;
>a : Symbol(C5.a, Decl(strictPropertyInitialization.ts, 37, 10))
constructor() {
this.a = 0;
>this.a : Symbol(C5.a, Decl(strictPropertyInitialization.ts, 37, 10))
>this : Symbol(C5, Decl(strictPropertyInitialization.ts, 33, 1))
>a : Symbol(C5.a, Decl(strictPropertyInitialization.ts, 37, 10))
}
}
// All code paths must contain assignment
class C6 {
>C6 : Symbol(C6, Decl(strictPropertyInitialization.ts, 42, 1))
a: number; // Error
>a : Symbol(C6.a, Decl(strictPropertyInitialization.ts, 46, 10))
constructor(cond: boolean) {
>cond : Symbol(cond, Decl(strictPropertyInitialization.ts, 48, 16))
if (cond) {
>cond : Symbol(cond, Decl(strictPropertyInitialization.ts, 48, 16))
return;
}
this.a = 0;
>this.a : Symbol(C6.a, Decl(strictPropertyInitialization.ts, 46, 10))
>this : Symbol(C6, Decl(strictPropertyInitialization.ts, 42, 1))
>a : Symbol(C6.a, Decl(strictPropertyInitialization.ts, 46, 10))
}
}
class C7 {
>C7 : Symbol(C7, Decl(strictPropertyInitialization.ts, 54, 1))
a: number;
>a : Symbol(C7.a, Decl(strictPropertyInitialization.ts, 56, 10))
constructor(cond: boolean) {
>cond : Symbol(cond, Decl(strictPropertyInitialization.ts, 58, 16))
if (cond) {
>cond : Symbol(cond, Decl(strictPropertyInitialization.ts, 58, 16))
this.a = 1;
>this.a : Symbol(C7.a, Decl(strictPropertyInitialization.ts, 56, 10))
>this : Symbol(C7, Decl(strictPropertyInitialization.ts, 54, 1))
>a : Symbol(C7.a, Decl(strictPropertyInitialization.ts, 56, 10))
return;
}
this.a = 0;
>this.a : Symbol(C7.a, Decl(strictPropertyInitialization.ts, 56, 10))
>this : Symbol(C7, Decl(strictPropertyInitialization.ts, 54, 1))
>a : Symbol(C7.a, Decl(strictPropertyInitialization.ts, 56, 10))
}
}
// Properties with string literal names aren't checked
class C8 {
>C8 : Symbol(C8, Decl(strictPropertyInitialization.ts, 65, 1))
a: number; // Error
>a : Symbol(C8.a, Decl(strictPropertyInitialization.ts, 69, 10))
"b": number;
0: number;
}
// No strict initialization checks for abstract members
abstract class C9 {
>C9 : Symbol(C9, Decl(strictPropertyInitialization.ts, 73, 1))
abstract a: number;
>a : Symbol(C9.a, Decl(strictPropertyInitialization.ts, 77, 19))
abstract b: number | undefined;
>b : Symbol(C9.b, Decl(strictPropertyInitialization.ts, 78, 23))
abstract c: number | null;
>c : Symbol(C9.c, Decl(strictPropertyInitialization.ts, 79, 35))
abstract d?: number;
>d : Symbol(C9.d, Decl(strictPropertyInitialization.ts, 80, 30))
}
// Properties with non-undefined types must be assigned before they can be accessed
// within their constructor
class C10 {
>C10 : Symbol(C10, Decl(strictPropertyInitialization.ts, 82, 1))
a: number;
>a : Symbol(C10.a, Decl(strictPropertyInitialization.ts, 87, 11))
b: number;
>b : Symbol(C10.b, Decl(strictPropertyInitialization.ts, 88, 14))
c?: number;
>c : Symbol(C10.c, Decl(strictPropertyInitialization.ts, 89, 14))
constructor() {
let x = this.a; // Error
>x : Symbol(x, Decl(strictPropertyInitialization.ts, 92, 11))
>this.a : Symbol(C10.a, Decl(strictPropertyInitialization.ts, 87, 11))
>this : Symbol(C10, Decl(strictPropertyInitialization.ts, 82, 1))
>a : Symbol(C10.a, Decl(strictPropertyInitialization.ts, 87, 11))
this.a = this.b; // Error
>this.a : Symbol(C10.a, Decl(strictPropertyInitialization.ts, 87, 11))
>this : Symbol(C10, Decl(strictPropertyInitialization.ts, 82, 1))
>a : Symbol(C10.a, Decl(strictPropertyInitialization.ts, 87, 11))
>this.b : Symbol(C10.b, Decl(strictPropertyInitialization.ts, 88, 14))
>this : Symbol(C10, Decl(strictPropertyInitialization.ts, 82, 1))
>b : Symbol(C10.b, Decl(strictPropertyInitialization.ts, 88, 14))
this.b = x;
>this.b : Symbol(C10.b, Decl(strictPropertyInitialization.ts, 88, 14))
>this : Symbol(C10, Decl(strictPropertyInitialization.ts, 82, 1))
>b : Symbol(C10.b, Decl(strictPropertyInitialization.ts, 88, 14))
>x : Symbol(x, Decl(strictPropertyInitialization.ts, 92, 11))
let y = this.c;
>y : Symbol(y, Decl(strictPropertyInitialization.ts, 95, 11))
>this.c : Symbol(C10.c, Decl(strictPropertyInitialization.ts, 89, 14))
>this : Symbol(C10, Decl(strictPropertyInitialization.ts, 82, 1))
>c : Symbol(C10.c, Decl(strictPropertyInitialization.ts, 89, 14))
}
}
@@ -0,0 +1,226 @@
=== tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts ===
// Properties with non-undefined types require initialization
class C1 {
>C1 : C1
a: number; // Error
>a : number
b: number | undefined;
>b : number | undefined
c: number | null; // Error
>c : number | null
>null : null
d?: number;
>d : number | undefined
}
// No strict initialization checks in ambient contexts
declare class C2 {
>C2 : C2
a: number;
>a : number
b: number | undefined;
>b : number | undefined
c: number | null;
>c : number | null
>null : null
d?: number;
>d : number | undefined
}
// No strict initialization checks for static members
class C3 {
>C3 : C3
static a: number;
>a : number
static b: number | undefined;
>b : number | undefined
static c: number | null;
>c : number | null
>null : null
static d?: number;
>d : number | undefined
}
// Initializer satisfies strict initialization check
class C4 {
>C4 : C4
a = 0;
>a : number
>0 : 0
b: number = 0;
>b : number
>0 : 0
c: string = "abc";
>c : string
>"abc" : "abc"
}
// Assignment in constructor satisfies strict initialization check
class C5 {
>C5 : C5
a: number;
>a : number
constructor() {
this.a = 0;
>this.a = 0 : 0
>this.a : number
>this : this
>a : number
>0 : 0
}
}
// All code paths must contain assignment
class C6 {
>C6 : C6
a: number; // Error
>a : number
constructor(cond: boolean) {
>cond : boolean
if (cond) {
>cond : boolean
return;
}
this.a = 0;
>this.a = 0 : 0
>this.a : number
>this : this
>a : number
>0 : 0
}
}
class C7 {
>C7 : C7
a: number;
>a : number
constructor(cond: boolean) {
>cond : boolean
if (cond) {
>cond : boolean
this.a = 1;
>this.a = 1 : 1
>this.a : number
>this : this
>a : number
>1 : 1
return;
}
this.a = 0;
>this.a = 0 : 0
>this.a : number
>this : this
>a : number
>0 : 0
}
}
// Properties with string literal names aren't checked
class C8 {
>C8 : C8
a: number; // Error
>a : number
"b": number;
0: number;
}
// No strict initialization checks for abstract members
abstract class C9 {
>C9 : C9
abstract a: number;
>a : number
abstract b: number | undefined;
>b : number | undefined
abstract c: number | null;
>c : number | null
>null : null
abstract d?: number;
>d : number | undefined
}
// Properties with non-undefined types must be assigned before they can be accessed
// within their constructor
class C10 {
>C10 : C10
a: number;
>a : number
b: number;
>b : number
c?: number;
>c : number | undefined
constructor() {
let x = this.a; // Error
>x : number
>this.a : number
>this : this
>a : number
this.a = this.b; // Error
>this.a = this.b : number
>this.a : number
>this : this
>a : number
>this.b : number
>this : this
>b : number
this.b = x;
>this.b = x : number
>this.b : number
>this : this
>b : number
>x : number
let y = this.c;
>y : number | undefined
>this.c : number | undefined
>this : this
>c : number | undefined
}
}
@@ -12,8 +12,10 @@ tests/cases/conformance/jsdoc/badTypeArguments.js(2,22): error TS1009: Trailing
/** @param {C.<number,>} y */
~
!!! error TS1009: Trailing comma not allowed.
function f(x, y) {
// @ts-ignore
/** @param {C.<number,>} skipped */
function f(x, y, skipped) {
return x.t + y.t;
}
var x = f({ t: 1000 }, { t: 3000 });
var x = f({ t: 1000 }, { t: 3000 }, { t: 5000 });
+13 -9
View File
@@ -8,22 +8,26 @@ declare class C<T> { t: T }
=== tests/cases/conformance/jsdoc/badTypeArguments.js ===
/** @param {C.<>} x */
/** @param {C.<number,>} y */
function f(x, y) {
// @ts-ignore
/** @param {C.<number,>} skipped */
function f(x, y, skipped) {
>f : Symbol(f, Decl(badTypeArguments.js, 0, 0))
>x : Symbol(x, Decl(badTypeArguments.js, 2, 11))
>y : Symbol(y, Decl(badTypeArguments.js, 2, 13))
>x : Symbol(x, Decl(badTypeArguments.js, 4, 11))
>y : Symbol(y, Decl(badTypeArguments.js, 4, 13))
>skipped : Symbol(skipped, Decl(badTypeArguments.js, 4, 16))
return x.t + y.t;
>x.t : Symbol(C.t, Decl(dummyType.d.ts, 0, 20))
>x : Symbol(x, Decl(badTypeArguments.js, 2, 11))
>x : Symbol(x, Decl(badTypeArguments.js, 4, 11))
>t : Symbol(C.t, Decl(dummyType.d.ts, 0, 20))
>y.t : Symbol(C.t, Decl(dummyType.d.ts, 0, 20))
>y : Symbol(y, Decl(badTypeArguments.js, 2, 13))
>y : Symbol(y, Decl(badTypeArguments.js, 4, 13))
>t : Symbol(C.t, Decl(dummyType.d.ts, 0, 20))
}
var x = f({ t: 1000 }, { t: 3000 });
>x : Symbol(x, Decl(badTypeArguments.js, 5, 3))
var x = f({ t: 1000 }, { t: 3000 }, { t: 5000 });
>x : Symbol(x, Decl(badTypeArguments.js, 7, 3))
>f : Symbol(f, Decl(badTypeArguments.js, 0, 0))
>t : Symbol(t, Decl(badTypeArguments.js, 5, 11))
>t : Symbol(t, Decl(badTypeArguments.js, 5, 24))
>t : Symbol(t, Decl(badTypeArguments.js, 7, 11))
>t : Symbol(t, Decl(badTypeArguments.js, 7, 24))
>t : Symbol(t, Decl(badTypeArguments.js, 7, 37))
+11 -5
View File
@@ -8,10 +8,13 @@ declare class C<T> { t: T }
=== tests/cases/conformance/jsdoc/badTypeArguments.js ===
/** @param {C.<>} x */
/** @param {C.<number,>} y */
function f(x, y) {
>f : (x: C<any>, y: C<number>) => any
// @ts-ignore
/** @param {C.<number,>} skipped */
function f(x, y, skipped) {
>f : (x: C<any>, y: C<number>, skipped: C<number>) => any
>x : C<any>
>y : C<number>
>skipped : C<number>
return x.t + y.t;
>x.t + y.t : any
@@ -22,14 +25,17 @@ function f(x, y) {
>y : C<number>
>t : number
}
var x = f({ t: 1000 }, { t: 3000 });
var x = f({ t: 1000 }, { t: 3000 }, { t: 5000 });
>x : any
>f({ t: 1000 }, { t: 3000 }) : any
>f : (x: C<any>, y: C<number>) => any
>f({ t: 1000 }, { t: 3000 }, { t: 5000 }) : any
>f : (x: C<any>, y: C<number>, skipped: C<number>) => any
>{ t: 1000 } : { t: number; }
>t : number
>1000 : 1000
>{ t: 3000 } : { t: number; }
>t : number
>3000 : 3000
>{ t: 5000 } : { t: number; }
>t : number
>5000 : 5000
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -23,6 +23,7 @@
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
@@ -6,7 +6,7 @@ interface Foo {
}
class A<P extends Partial<Foo>> {
props: Readonly<P>
constructor(public props: Readonly<P>) {}
doSomething() {
this.props.foo && this.props.foo()
}
@@ -19,7 +19,7 @@ interface Banana {
}
class Monkey<T extends Banana | undefined> {
a: T;
constructor(public a: T) {}
render() {
if (this.a) {
this.a.color;
@@ -96,7 +96,8 @@ var __extends = (this && this.__extends) || (function () {
};
})();
var A = /** @class */ (function () {
function A() {
function A(props) {
this.props = props;
}
A.prototype.doSomething = function () {
this.props.foo && this.props.foo();
@@ -104,7 +105,8 @@ var A = /** @class */ (function () {
return A;
}());
var Monkey = /** @class */ (function () {
function Monkey() {
function Monkey(a) {
this.a = a;
}
Monkey.prototype.render = function () {
if (this.a) {
@@ -14,24 +14,24 @@ class A<P extends Partial<Foo>> {
>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
>Foo : Symbol(Foo, Decl(typeVariableTypeGuards.ts, 0, 0))
props: Readonly<P>
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
constructor(public props: Readonly<P>) {}
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 7, 16))
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
>P : Symbol(P, Decl(typeVariableTypeGuards.ts, 6, 8))
doSomething() {
>doSomething : Symbol(A.doSomething, Decl(typeVariableTypeGuards.ts, 7, 22))
>doSomething : Symbol(A.doSomething, Decl(typeVariableTypeGuards.ts, 7, 45))
this.props.foo && this.props.foo()
>this.props.foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
>this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
>this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 7, 16))
>this : Symbol(A, Decl(typeVariableTypeGuards.ts, 4, 1))
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 7, 16))
>foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
>this.props.foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
>this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
>this.props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 7, 16))
>this : Symbol(A, Decl(typeVariableTypeGuards.ts, 4, 1))
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 6, 33))
>props : Symbol(A.props, Decl(typeVariableTypeGuards.ts, 7, 16))
>foo : Symbol(foo, Decl(typeVariableTypeGuards.ts, 2, 15))
}
}
@@ -50,23 +50,23 @@ class Monkey<T extends Banana | undefined> {
>T : Symbol(T, Decl(typeVariableTypeGuards.ts, 19, 13))
>Banana : Symbol(Banana, Decl(typeVariableTypeGuards.ts, 11, 1))
a: T;
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
constructor(public a: T) {}
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
>T : Symbol(T, Decl(typeVariableTypeGuards.ts, 19, 13))
render() {
>render : Symbol(Monkey.render, Decl(typeVariableTypeGuards.ts, 20, 9))
>render : Symbol(Monkey.render, Decl(typeVariableTypeGuards.ts, 20, 31))
if (this.a) {
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
>this : Symbol(Monkey, Decl(typeVariableTypeGuards.ts, 17, 1))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
this.a.color;
>this.a.color : Symbol(Banana.color, Decl(typeVariableTypeGuards.ts, 15, 18))
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
>this : Symbol(Monkey, Decl(typeVariableTypeGuards.ts, 17, 1))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
>color : Symbol(Banana.color, Decl(typeVariableTypeGuards.ts, 15, 18))
}
}
@@ -86,15 +86,15 @@ class BigMonkey extends Monkey<BigBanana> {
>render : Symbol(BigMonkey.render, Decl(typeVariableTypeGuards.ts, 31, 43))
if (this.a) {
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
>this : Symbol(BigMonkey, Decl(typeVariableTypeGuards.ts, 29, 1))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
this.a.color;
>this.a.color : Symbol(Banana.color, Decl(typeVariableTypeGuards.ts, 15, 18))
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>this.a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
>this : Symbol(BigMonkey, Decl(typeVariableTypeGuards.ts, 29, 1))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 19, 44))
>a : Symbol(Monkey.a, Decl(typeVariableTypeGuards.ts, 20, 16))
>color : Symbol(Banana.color, Decl(typeVariableTypeGuards.ts, 15, 18))
}
}
@@ -14,7 +14,7 @@ class A<P extends Partial<Foo>> {
>Partial : Partial<T>
>Foo : Foo
props: Readonly<P>
constructor(public props: Readonly<P>) {}
>props : Readonly<P>
>Readonly : Readonly<T>
>P : P
@@ -52,7 +52,7 @@ class Monkey<T extends Banana | undefined> {
>T : T
>Banana : Banana
a: T;
constructor(public a: T) {}
>a : T
>T : T
File diff suppressed because it is too large Load Diff
@@ -11,7 +11,7 @@ type Data<T> = {
};
class Parent<M> {
private data: Data<M>;
constructor(private data: Data<M>) {}
getData(): Data<M> {
return this.data;
}
@@ -7,7 +7,7 @@ interface Foo {
}
class A<P extends Partial<Foo>> {
props: Readonly<P>
constructor(public props: Readonly<P>) {}
doSomething() {
this.props.foo && this.props.foo()
}
@@ -20,7 +20,7 @@ interface Banana {
}
class Monkey<T extends Banana | undefined> {
a: T;
constructor(public a: T) {}
render() {
if (this.a) {
this.a.color;
@@ -0,0 +1,101 @@
// @strict: true
// @declaration: true
// Properties with non-undefined types require initialization
class C1 {
a: number; // Error
b: number | undefined;
c: number | null; // Error
d?: number;
}
// No strict initialization checks in ambient contexts
declare class C2 {
a: number;
b: number | undefined;
c: number | null;
d?: number;
}
// No strict initialization checks for static members
class C3 {
static a: number;
static b: number | undefined;
static c: number | null;
static d?: number;
}
// Initializer satisfies strict initialization check
class C4 {
a = 0;
b: number = 0;
c: string = "abc";
}
// Assignment in constructor satisfies strict initialization check
class C5 {
a: number;
constructor() {
this.a = 0;
}
}
// All code paths must contain assignment
class C6 {
a: number; // Error
constructor(cond: boolean) {
if (cond) {
return;
}
this.a = 0;
}
}
class C7 {
a: number;
constructor(cond: boolean) {
if (cond) {
this.a = 1;
return;
}
this.a = 0;
}
}
// Properties with string literal names aren't checked
class C8 {
a: number; // Error
"b": number;
0: number;
}
// No strict initialization checks for abstract members
abstract class C9 {
abstract a: number;
abstract b: number | undefined;
abstract c: number | null;
abstract d?: number;
}
// Properties with non-undefined types must be assigned before they can be accessed
// within their constructor
class C10 {
a: number;
b: number;
c?: number;
constructor() {
let x = this.a; // Error
this.a = this.b; // Error
this.b = x;
let y = this.c;
}
}
@@ -0,0 +1,79 @@
// @strict: true
// @declaration: true
// Suppress strict property initialization check
class C1 {
a!: number;
b: string; // Error
}
// Suppress definite assignment check in constructor
class C2 {
a!: number;
constructor() {
let x = this.a;
}
}
// Definite assignment assertion requires type annotation, no initializer, no static modifier
class C3 {
a! = 1;
b!: number = 1;
static c!: number;
}
// Definite assignment assertion not permitted in ambient context
declare class C4 {
a!: number;
}
// Definite assignment assertion not permitted on abstract property
abstract class C5 {
abstract a!: number;
}
// Suppress definite assignment check for variable
function f1() {
let x!: number;
let y = x;
var a!: number;
var b = a;
}
function f2() {
let x!: string | number;
if (typeof x === "string") {
let s: string = x;
}
else {
let n: number = x;
}
}
function f3() {
let x!: number;
const g = () => {
x = 1;
}
g();
let y = x;
}
// Definite assignment assertion requires type annotation and no initializer
function f4() {
let a!;
let b! = 1;
let c!: number = 1;
}
// Definite assignment assertion not permitted in ambient context
declare let v1!: number;
declare var v2!: number;
@@ -8,7 +8,9 @@ declare class C<T> { t: T }
// @Filename: badTypeArguments.js
/** @param {C.<>} x */
/** @param {C.<number,>} y */
function f(x, y) {
// @ts-ignore
/** @param {C.<number,>} skipped */
function f(x, y, skipped) {
return x.t + y.t;
}
var x = f({ t: 1000 }, { t: 3000 });
var x = f({ t: 1000 }, { t: 3000 }, { t: 5000 });
@@ -0,0 +1,36 @@
// @strict: true
// Repro from #20138
class C { }
function f1<T extends C>(v: T | string): void {
if (v instanceof C) {
const x: T = v;
}
else {
const s: string = v;
}
}
class D { }
function f2<T extends C, U extends D>(v: T | U) {
if (v instanceof C) {
const x: T = v;
}
else {
const y: U = v;
}
}
class E { x: string | undefined }
function f3<T extends E>(v: T | { x: string }) {
if (v instanceof E) {
const x: T = v;
}
else {
const y: { x: string } = v;
}
}
@@ -3,7 +3,8 @@
"outDir": "./built",
"allowJs": true,
"checkJs": true,
"lib": ["dom", "es2017"]
"lib": ["dom", "es2017"],
"types": []
},
"include": [
"./node_modules/chrome-devtools-frontend/front_end/**/*.js"