Merge branch 'master' into watchImprovements

This commit is contained in:
Sheetal Nandi
2017-07-20 09:49:30 -07:00
83 changed files with 1912 additions and 429 deletions
+34 -24
View File
@@ -19,47 +19,57 @@ function main(): void {
// Acquire the version from the package.json file and modify it appropriately.
const packageJsonFilePath = ts.normalizePath(sys.args[0]);
const packageJsonContents = sys.readFile(packageJsonFilePath);
const packageJsonValue: PackageJson = JSON.parse(packageJsonContents);
const packageJsonValue: PackageJson = JSON.parse(sys.readFile(packageJsonFilePath));
const nightlyVersion = getNightlyVersionString(packageJsonValue.version);
// Modify the package.json structure
packageJsonValue.version = nightlyVersion;
const { majorMinor, patch } = parsePackageJsonVersion(packageJsonValue.version);
const nightlyPatch = getNightlyPatch(patch);
// Acquire and modify the source file that exposes the version string.
const tsFilePath = ts.normalizePath(sys.args[1]);
const tsFileContents = sys.readFile(tsFilePath);
const versionAssignmentRegExp = /export\s+const\s+version\s+=\s+".*";/;
const modifiedTsFileContents = tsFileContents.replace(versionAssignmentRegExp, `export const version = "${nightlyVersion}";`);
const tsFileContents = ts.sys.readFile(tsFilePath);
const modifiedTsFileContents = updateTsFile(tsFilePath, tsFileContents, majorMinor, patch, nightlyPatch);
// Ensure we are actually changing something - the user probably wants to know that the update failed.
if (tsFileContents === modifiedTsFileContents) {
let err = `\n '${tsFilePath}' was not updated while configuring for a nightly publish.\n `;
if (tsFileContents.match(versionAssignmentRegExp)) {
err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`;
}
else {
err += `The file seems to no longer have a string matching '${versionAssignmentRegExp}'.`;
}
err += `Ensure that you have not already run this script; otherwise, erase your changes using 'git checkout -- "${tsFilePath}"'.`;
throw err + "\n";
}
// Finally write the changes to disk.
// Modify the package.json structure
packageJsonValue.version = `${majorMinor}.${nightlyPatch}`;
sys.writeFile(packageJsonFilePath, JSON.stringify(packageJsonValue, /*replacer:*/ undefined, /*space:*/ 4))
sys.writeFile(tsFilePath, modifiedTsFileContents);
}
function getNightlyVersionString(versionString: string): string {
// If the version string already contains "-nightly",
// then get the base string and update based on that.
const dashNightlyPos = versionString.indexOf("-dev");
if (dashNightlyPos >= 0) {
versionString = versionString.slice(0, dashNightlyPos);
function updateTsFile(tsFilePath: string, tsFileContents: string, majorMinor: string, patch: string, nightlyPatch: string): string {
const majorMinorRgx = /export const versionMajorMinor = "(\d+\.\d+)"/;
const majorMinorMatch = majorMinorRgx.exec(tsFileContents);
ts.Debug.assert(majorMinorMatch !== null, "", () => `The file seems to no longer have a string matching '${majorMinorRgx}'.`);
const parsedMajorMinor = majorMinorMatch[1];
ts.Debug.assert(parsedMajorMinor === majorMinor, "versionMajorMinor does not match.", () => `${tsFilePath}: '${parsedMajorMinor}'; package.json: '${majorMinor}'`);
const versionRgx = /export const version = `\$\{versionMajorMinor\}\.(\d)`;/;
const patchMatch = versionRgx.exec(tsFileContents);
ts.Debug.assert(patchMatch !== null, "The file seems to no longer have a string matching", () => versionRgx.toString());
const parsedPatch = patchMatch[1];
if (parsedPatch !== patch) {
throw new Error(`patch does not match. ${tsFilePath}: '${parsedPatch}; package.json: '${patch}'`);
}
return tsFileContents.replace(versionRgx, `export const version = \`\${versionMajorMinor}.${nightlyPatch}\`;`);
}
function parsePackageJsonVersion(versionString: string): { majorMinor: string, patch: string } {
const versionRgx = /(\d+\.\d+)\.(\d+)($|\-)/;
const match = versionString.match(versionRgx);
ts.Debug.assert(match !== null, "package.json 'version' should match", () => versionRgx.toString());
return { majorMinor: match[1], patch: match[2] };
}
/** e.g. 0-dev.20170707 */
function getNightlyPatch(plainPatch: string): string {
// We're going to append a representation of the current time at the end of the current version.
// String.prototype.toISOString() returns a 24-character string formatted as 'YYYY-MM-DDTHH:mm:ss.sssZ',
// but we'd prefer to just remove separators and limit ourselves to YYYYMMDD.
@@ -67,7 +77,7 @@ function getNightlyVersionString(versionString: string): string {
const now = new Date();
const timeStr = now.toISOString().replace(/:|T|\.|-/g, "").slice(0, 8);
return `${versionString}-dev.${timeStr}`;
return `${plainPatch}-dev.${timeStr}`;
}
main();
+1 -1
View File
@@ -19,7 +19,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
ts.forEachChild(node, recur);
}
function check(types: ts.TypeNode[]): void {
function check(types: ReadonlyArray<ts.TypeNode>): void {
let expectedStart = types[0].end + 2; // space, | or &
for (let i = 1; i < types.length; i++) {
const currentType = types[i];
+17 -13
View File
@@ -308,7 +308,7 @@ namespace ts {
* @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.)
* @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations.
*/
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean): Symbol {
Debug.assert(!hasDynamicName(node));
const isDefaultExport = hasModifier(node, ModifierFlags.Default);
@@ -345,15 +345,20 @@ namespace ts {
// you have multiple 'vars' with the same name in the same container). In this case
// just add this node into the declarations list of the symbol.
symbol = symbolTable.get(name);
if (!symbol) {
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
}
if (name && (includes & SymbolFlags.Classifiable)) {
if (includes & SymbolFlags.Classifiable) {
classifiableNames.set(name, true);
}
if (symbol.flags & excludes) {
if (!symbol) {
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
if (isReplaceableByMethod) symbol.isReplaceableByMethod = true;
}
else if (isReplaceableByMethod && !symbol.isReplaceableByMethod) {
// A symbol already exists, so don't add this as a declaration.
return symbol;
}
else if (symbol.flags & excludes) {
if (symbol.isReplaceableByMethod) {
// Javascript constructor-declared symbols can be discarded in favor of
// prototype symbols like methods.
@@ -1327,7 +1332,7 @@ namespace ts {
function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) {
const name = !isOmittedExpression(node) ? node.name : undefined;
if (isBindingPattern(name)) {
for (const child of <ArrayBindingElement[]>name.elements) {
for (const child of name.elements) {
bindInitializedVariableFlow(child);
}
}
@@ -2061,8 +2066,10 @@ namespace ts {
case SyntaxKind.Parameter:
return bindParameter(<ParameterDeclaration>node);
case SyntaxKind.VariableDeclaration:
return bindVariableDeclarationOrBindingElement(<VariableDeclaration>node);
case SyntaxKind.BindingElement:
return bindVariableDeclarationOrBindingElement(<VariableDeclaration | BindingElement>node);
node.flowNode = currentFlow;
return bindVariableDeclarationOrBindingElement(<BindingElement>node);
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
return bindPropertyWorker(node as PropertyDeclaration | PropertySignature);
@@ -2342,11 +2349,8 @@ namespace ts {
// this.foo assignment in a JavaScript class
// Bind this property to the containing class
const containingClass = container.parent;
const symbol = declareSymbol(hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None);
if (symbol) {
// symbols declared through 'this' property assignements can be overwritten by subsequent method declarations
(symbol as Symbol).isReplaceableByMethod = true;
}
const symbolTable = hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members;
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true);
break;
}
}
+135 -47
View File
@@ -117,6 +117,7 @@ namespace ts {
},
getParameterType: getTypeAtPosition,
getReturnTypeOfSignature,
getNullableType,
getNonNullableType,
typeToTypeNode: nodeBuilder.typeToTypeNode,
indexInfoToIndexSignatureDeclaration: nodeBuilder.indexInfoToIndexSignatureDeclaration,
@@ -2669,7 +2670,7 @@ namespace ts {
entityName = nameIdentifier;
}
let typeArgumentNodes: TypeNode[] | undefined;
let typeArgumentNodes: ReadonlyArray<TypeNode> | undefined;
if (typeArguments.length > 0) {
const typeParameterCount = (type.target.typeParameters || emptyArray).length;
typeArgumentNodes = mapToTypeNodes(typeArguments.slice(i, typeParameterCount), context);
@@ -2906,7 +2907,7 @@ namespace ts {
function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName {
Debug.assert(chain && 0 <= index && index < chain.length);
const symbol = chain[index];
let typeParameterNodes: TypeNode[] | undefined;
let typeParameterNodes: ReadonlyArray<TypeNode> | undefined;
if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index > 0) {
const parentSymbol = chain[index - 1];
let typeParameters: TypeParameter[];
@@ -3301,7 +3302,7 @@ namespace ts {
function writeTypeReference(type: TypeReference, flags: TypeFormatFlags) {
const typeArguments = type.typeArguments || emptyArray;
if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) {
writeType(typeArguments[0], TypeFormatFlags.InElementType);
writeType(typeArguments[0], TypeFormatFlags.InElementType | TypeFormatFlags.InArrayType);
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
}
@@ -3426,9 +3427,15 @@ namespace ts {
}
function writeTypeOfSymbol(type: ObjectType, typeFormatFlags?: TypeFormatFlags) {
if (typeFormatFlags & TypeFormatFlags.InArrayType) {
writePunctuation(writer, SyntaxKind.OpenParenToken);
}
writeKeyword(writer, SyntaxKind.TypeOfKeyword);
writeSpace(writer);
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Value, SymbolFormatFlags.None, typeFormatFlags);
if (typeFormatFlags & TypeFormatFlags.InArrayType) {
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
}
function writePropertyWithModifiers(prop: Symbol) {
@@ -3666,7 +3673,7 @@ namespace ts {
}
}
function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
function buildDisplayForTypeParametersAndDelimiters(typeParameters: ReadonlyArray<TypeParameter>, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
if (typeParameters && typeParameters.length) {
writePunctuation(writer, SyntaxKind.LessThanToken);
buildDisplayForCommaSeparatedList(typeParameters, writer, p => buildTypeParameterDisplay(p, writer, enclosingDeclaration, flags, symbolStack));
@@ -3674,7 +3681,7 @@ namespace ts {
}
}
function buildDisplayForCommaSeparatedList<T>(list: T[], writer: SymbolWriter, action: (item: T) => void) {
function buildDisplayForCommaSeparatedList<T>(list: ReadonlyArray<T>, writer: SymbolWriter, action: (item: T) => void) {
for (let i = 0; i < list.length; i++) {
if (i > 0) {
writePunctuation(writer, SyntaxKind.CommaToken);
@@ -3684,7 +3691,7 @@ namespace ts {
}
}
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node) {
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: ReadonlyArray<TypeParameter>, mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node) {
if (typeParameters && typeParameters.length) {
writePunctuation(writer, SyntaxKind.LessThanToken);
let flags = TypeFormatFlags.InFirstTypeArgument;
@@ -4088,8 +4095,8 @@ namespace ts {
/** Return the inferred type for a binding element */
function getTypeForBindingElement(declaration: BindingElement): Type {
const pattern = <BindingPattern>declaration.parent;
const parentType = getTypeForBindingElementParent(<VariableLikeDeclaration>pattern.parent);
const pattern = declaration.parent;
const parentType = getTypeForBindingElementParent(pattern.parent);
// If parent has the unknown (error) type, then so does this binding element
if (parentType === unknownType) {
return unknownType;
@@ -4134,7 +4141,8 @@ namespace ts {
// or otherwise the type of the string index signature.
const text = getTextOfPropertyName(name);
type = getTypeOfPropertyOfType(parentType, text) ||
const declaredType = getTypeOfPropertyOfType(parentType, text);
type = declaredType && getFlowTypeOfReference(declaration, declaredType) ||
isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
getIndexTypeOfType(parentType, IndexKind.String);
if (!type) {
@@ -4736,7 +4744,7 @@ namespace ts {
// Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set.
// The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set
// in-place and returns the same array.
function appendTypeParameters(typeParameters: TypeParameter[], declarations: TypeParameterDeclaration[]): TypeParameter[] {
function appendTypeParameters(typeParameters: TypeParameter[], declarations: ReadonlyArray<TypeParameterDeclaration>): TypeParameter[] {
for (const declaration of declarations) {
const tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration));
if (!typeParameters) {
@@ -4823,14 +4831,14 @@ namespace ts {
return getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>type.symbol.valueDeclaration);
}
function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[], location: Node): Signature[] {
function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray<TypeNode>, location: Node): Signature[] {
const typeArgCount = length(typeArgumentNodes);
const isJavaScript = isInJavaScriptFile(location);
return filter(getSignaturesOfType(type, SignatureKind.Construct),
sig => (isJavaScript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= length(sig.typeParameters));
}
function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[], location: Node): Signature[] {
function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray<TypeNode>, location: Node): Signature[] {
const signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location);
const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode);
return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments) : sig);
@@ -6870,8 +6878,19 @@ namespace ts {
return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference;
}
function getPrimitiveTypeFromJSDocTypeReference(node: TypeReferenceNode): Type {
function getIntendedTypeFromJSDocTypeReference(node: TypeReferenceNode): Type {
if (isIdentifier(node.typeName)) {
if (node.typeName.text === "Object") {
if (node.typeArguments && node.typeArguments.length === 2) {
const indexed = getTypeFromTypeNode(node.typeArguments[0]);
const target = getTypeFromTypeNode(node.typeArguments[1]);
const index = createIndexInfo(target, /*isReadonly*/ false);
if (indexed === stringType || indexed === numberType) {
return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexed === stringType && index, indexed === numberType && index);
}
}
return anyType;
}
switch (node.typeName.text) {
case "String":
return stringType;
@@ -6885,8 +6904,6 @@ namespace ts {
return undefinedType;
case "Null":
return nullType;
case "Object":
return anyType;
case "Function":
case "function":
return globalFunctionType;
@@ -6912,7 +6929,7 @@ namespace ts {
let type: Type;
let meaning = SymbolFlags.Type;
if (isJSDocTypeReference(node)) {
type = getPrimitiveTypeFromJSDocTypeReference(node);
type = getIntendedTypeFromJSDocTypeReference(node);
meaning |= SymbolFlags.Value;
}
if (!type) {
@@ -9954,6 +9971,11 @@ namespace ts {
neverType;
}
/**
* Add undefined or null or both to a type if they are missing.
* @param type - type to add undefined and/or null to if not present
* @param flags - Either TypeFlags.Undefined or TypeFlags.Null, or both
*/
function getNullableType(type: Type, flags: TypeFlags): Type {
const missing = (flags & ~type.flags) & (TypeFlags.Undefined | TypeFlags.Null);
return missing === 0 ? type :
@@ -10656,7 +10678,7 @@ namespace ts {
// The result is undefined if the reference isn't a dotted name. We prefix nodes
// occurring in an apparent type position with '@' because the control flow type
// of such nodes may be based on the apparent type instead of the declared type.
function getFlowCacheKey(node: Node): string {
function getFlowCacheKey(node: Node): string | undefined {
if (node.kind === SyntaxKind.Identifier) {
const symbol = getResolvedSymbol(<Identifier>node);
return symbol !== unknownSymbol ? (isApparentTypePosition(node) ? "@" : "") + getSymbolId(symbol) : undefined;
@@ -10666,7 +10688,14 @@ namespace ts {
}
if (node.kind === SyntaxKind.PropertyAccessExpression) {
const key = getFlowCacheKey((<PropertyAccessExpression>node).expression);
return key && key + "." + (<PropertyAccessExpression>node).name.text;
return key && key + "." + unescapeLeadingUnderscores((<PropertyAccessExpression>node).name.text);
}
if (node.kind === SyntaxKind.BindingElement) {
const container = (node as BindingElement).parent.parent;
const key = container.kind === SyntaxKind.BindingElement ? getFlowCacheKey(container) : (container.initializer && getFlowCacheKey(container.initializer));
const text = getBindingElementNameText(node as BindingElement);
const result = key && text && (key + "." + text);
return result;
}
return undefined;
}
@@ -10682,6 +10711,28 @@ namespace ts {
return undefined;
}
function getBindingElementNameText(element: BindingElement): string | undefined {
if (element.parent.kind === SyntaxKind.ObjectBindingPattern) {
const name = element.propertyName || element.name;
switch (name.kind) {
case SyntaxKind.Identifier:
return unescapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
if (isComputedNonLiteralName(name as PropertyName)) return undefined;
return (name.expression as LiteralExpression).text;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
return name.text;
default:
// Per types, array and object binding patterns remain, however they should never be present if propertyName is not defined
Debug.fail("Unexpected name kind for binding element name");
}
}
else {
return "" + element.parent.elements.indexOf(element);
}
}
function isMatchingReference(source: Node, target: Node): boolean {
switch (source.kind) {
case SyntaxKind.Identifier:
@@ -10696,6 +10747,17 @@ namespace ts {
return target.kind === SyntaxKind.PropertyAccessExpression &&
(<PropertyAccessExpression>source).name.text === (<PropertyAccessExpression>target).name.text &&
isMatchingReference((<PropertyAccessExpression>source).expression, (<PropertyAccessExpression>target).expression);
case SyntaxKind.BindingElement:
if (target.kind !== SyntaxKind.PropertyAccessExpression) return false;
const t = target as PropertyAccessExpression;
if (t.name.text !== getBindingElementNameText(source as BindingElement)) return false;
if (source.parent.parent.kind === SyntaxKind.BindingElement && isMatchingReference(source.parent.parent, t.expression)) {
return true;
}
if (source.parent.parent.kind === SyntaxKind.VariableDeclaration) {
const maybeId = (source.parent.parent as VariableDeclaration).initializer;
return maybeId && isMatchingReference(maybeId, t.expression);
}
}
return false;
}
@@ -11486,6 +11548,10 @@ namespace ts {
const cache = flowLoopCaches[id] || (flowLoopCaches[id] = createMap<Type>());
if (!key) {
key = getFlowCacheKey(reference);
// No cache key is generated when binding patterns are in unnarrowable situations
if (!key) {
return declaredType;
}
}
const cached = cache.get(key);
if (cached) {
@@ -12602,7 +12668,7 @@ namespace ts {
}
}
}
if (noImplicitThis) {
if (noImplicitThis || isInJavaScriptFile(func)) {
const containingLiteral = getContainingObjectLiteral(func);
if (containingLiteral) {
// We have an object literal method. Check if the containing object literal has a contextual type
@@ -14846,7 +14912,7 @@ namespace ts {
}
}
function getSpreadArgumentIndex(args: Expression[]): number {
function getSpreadArgumentIndex(args: ReadonlyArray<Expression>): number {
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg && arg.kind === SyntaxKind.SpreadElement) {
@@ -14856,7 +14922,7 @@ namespace ts {
return -1;
}
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature, signatureHelpTrailingComma = false) {
function hasCorrectArity(node: CallLikeExpression, args: ReadonlyArray<Expression>, signature: Signature, signatureHelpTrailingComma = false) {
let argCount: number; // Apparent number of arguments we will have in this call
let typeArguments: NodeArray<TypeNode>; // Type arguments (undefined if none)
let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments
@@ -14967,7 +15033,7 @@ namespace ts {
return getSignatureInstantiation(signature, getInferredTypes(context));
}
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): Type[] {
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray<Expression>, excludeArgument: boolean[], context: InferenceContext): Type[] {
// Clear out all the inference results from the last time inferTypeArguments was called on this context
for (const inference of context.inferences) {
// As an optimization, we don't have to clear (and later recompute) inferred types
@@ -15055,7 +15121,7 @@ namespace ts {
return getInferredTypes(context);
}
function checkTypeArguments(signature: Signature, typeArgumentNodes: TypeNode[], typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean {
function checkTypeArguments(signature: Signature, typeArgumentNodes: ReadonlyArray<TypeNode>, typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean {
const typeParameters = signature.typeParameters;
let typeArgumentsAreAssignable = true;
let mapper: TypeMapper;
@@ -15119,7 +15185,13 @@ namespace ts {
return checkTypeRelatedTo(attributesType, paramType, relation, /*errorNode*/ undefined, headMessage);
}
function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[], reportErrors: boolean) {
function checkApplicableSignature(
node: CallLikeExpression,
args: ReadonlyArray<Expression>,
signature: Signature,
relation: Map<RelationComparisonResult>,
excludeArgument: boolean[],
reportErrors: boolean) {
if (isJsxOpeningLikeElement(node)) {
return checkApplicableSignatureForJsxOpeningLikeElement(<JsxOpeningLikeElement>node, signature, relation);
}
@@ -15187,16 +15259,16 @@ namespace ts {
* If 'node' is a Decorator, the argument list will be `undefined`, and its arguments and types
* will be supplied from calls to `getEffectiveArgumentCount` and `getEffectiveArgumentType`.
*/
function getEffectiveCallArguments(node: CallLikeExpression): Expression[] {
let args: Expression[];
function getEffectiveCallArguments(node: CallLikeExpression): ReadonlyArray<Expression> {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
const template = (<TaggedTemplateExpression>node).template;
args = [undefined];
const args: Expression[] = [undefined];
if (template.kind === SyntaxKind.TemplateExpression) {
forEach((<TemplateExpression>template).templateSpans, span => {
args.push(span.expression);
});
}
return args;
}
else if (node.kind === SyntaxKind.Decorator) {
// For a decorator, we return undefined as we will determine
@@ -15205,13 +15277,11 @@ namespace ts {
return undefined;
}
else if (isJsxOpeningLikeElement(node)) {
args = node.attributes.properties.length > 0 ? [node.attributes] : emptyArray;
return node.attributes.properties.length > 0 ? [node.attributes] : emptyArray;
}
else {
args = node.arguments || emptyArray;
return node.arguments || emptyArray;
}
return args;
}
@@ -15228,7 +15298,7 @@ namespace ts {
* us to match a property decorator.
* Otherwise, the argument count is the length of the 'args' array.
*/
function getEffectiveArgumentCount(node: CallLikeExpression, args: Expression[], signature: Signature) {
function getEffectiveArgumentCount(node: CallLikeExpression, args: ReadonlyArray<Expression>, signature: Signature) {
if (node.kind === SyntaxKind.Decorator) {
switch (node.parent.kind) {
case SyntaxKind.ClassDeclaration:
@@ -15460,7 +15530,7 @@ namespace ts {
/**
* Gets the effective argument expression for an argument in a call expression.
*/
function getEffectiveArgument(node: CallLikeExpression, args: Expression[], argIndex: number) {
function getEffectiveArgument(node: CallLikeExpression, args: ReadonlyArray<Expression>, argIndex: number) {
// For a decorator or the first argument of a tagged template expression we return undefined.
if (node.kind === SyntaxKind.Decorator ||
(argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression)) {
@@ -15492,7 +15562,7 @@ namespace ts {
const isDecorator = node.kind === SyntaxKind.Decorator;
const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node);
let typeArguments: TypeNode[];
let typeArguments: ReadonlyArray<TypeNode>;
if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) {
typeArguments = (<CallExpression>node).typeArguments;
@@ -16256,15 +16326,19 @@ namespace ts {
}
function checkAssertion(node: AssertionExpression) {
const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(node.expression)));
return checkAssertionWorker(node, node.type, node.expression);
}
checkSourceElement(node.type);
const targetType = getTypeFromTypeNode(node.type);
function checkAssertionWorker(errNode: Node, type: TypeNode, expression: UnaryExpression | Expression, checkMode?: CheckMode) {
const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(expression, checkMode)));
checkSourceElement(type);
const targetType = getTypeFromTypeNode(type);
if (produceDiagnostics && targetType !== unknownType) {
const widenedType = getWidenedType(exprType);
if (!isTypeComparableTo(targetType, widenedType)) {
checkTypeComparableTo(exprType, targetType, node, Diagnostics.Type_0_cannot_be_converted_to_type_1);
checkTypeComparableTo(exprType, targetType, errNode, Diagnostics.Type_0_cannot_be_converted_to_type_1);
}
}
return targetType;
@@ -17001,7 +17075,7 @@ namespace ts {
}
/** Note: If property cannot be a SpreadAssignment, then allProperties does not need to be provided */
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: ObjectLiteralElementLike[]) {
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: ReadonlyArray<ObjectLiteralElementLike>) {
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
const name = <PropertyName>(<PropertyAssignment>property).name;
if (name.kind === SyntaxKind.ComputedPropertyName) {
@@ -17735,6 +17809,18 @@ namespace ts {
return type;
}
function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type {
if (isInJavaScriptFile(node) && node.jsDoc) {
const typecasts = flatMap(node.jsDoc, doc => filter(doc.tags, tag => tag.kind === SyntaxKind.JSDocTypeTag));
if (typecasts && typecasts.length) {
// We should have already issued an error if there were multiple type jsdocs
const cast = typecasts[0] as JSDocTypeTag;
return checkAssertionWorker(cast, cast.typeExpression.type, node.expression, checkMode);
}
}
return checkExpression(node.expression, checkMode);
}
function checkExpressionWorker(node: Expression, checkMode: CheckMode): Type {
switch (node.kind) {
case SyntaxKind.Identifier:
@@ -17774,7 +17860,7 @@ namespace ts {
case SyntaxKind.TaggedTemplateExpression:
return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.ParenthesizedExpression:
return checkExpression((<ParenthesizedExpression>node).expression, checkMode);
return checkParenthesizedExpression(<ParenthesizedExpression>node, checkMode);
case SyntaxKind.ClassExpression:
return checkClassExpression(<ClassExpression>node);
case SyntaxKind.FunctionExpression:
@@ -17910,6 +17996,8 @@ namespace ts {
return;
}
checkSourceElement(node.type);
const { parameterName } = node;
if (isThisTypePredicate(typePredicate)) {
getTypeFromThisTypeNode(parameterName as ThisTypeNode);
@@ -18433,7 +18521,7 @@ namespace ts {
checkDecorators(node);
}
function checkTypeArgumentConstraints(typeParameters: TypeParameter[], typeArgumentNodes: TypeNode[]): boolean {
function checkTypeArgumentConstraints(typeParameters: TypeParameter[], typeArgumentNodes: ReadonlyArray<TypeNode>): boolean {
const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters);
let typeArguments: Type[];
let mapper: TypeMapper;
@@ -20879,7 +20967,7 @@ namespace ts {
/**
* Check each type parameter and check that type parameters have no duplicate type parameter declarations
*/
function checkTypeParameters(typeParameterDeclarations: TypeParameterDeclaration[]) {
function checkTypeParameters(typeParameterDeclarations: ReadonlyArray<TypeParameterDeclaration>) {
if (typeParameterDeclarations) {
let seenDefault = false;
for (let i = 0; i < typeParameterDeclarations.length; i++) {
@@ -22186,8 +22274,8 @@ namespace ts {
// Grammar checking
checkGrammarSourceFile(node);
potentialThisCollisions.length = 0;
potentialNewTargetCollisions.length = 0;
clear(potentialThisCollisions);
clear(potentialNewTargetCollisions);
deferredNodes = [];
deferredUnusedIdentifierNodes = produceDiagnostics && noUnusedIdentifiers ? [] : undefined;
@@ -22213,12 +22301,12 @@ namespace ts {
if (potentialThisCollisions.length) {
forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
potentialThisCollisions.length = 0;
clear(potentialThisCollisions);
}
if (potentialNewTargetCollisions.length) {
forEach(potentialNewTargetCollisions, checkIfNewTargetIsCapturedInEnclosingScope);
potentialNewTargetCollisions.length = 0;
clear(potentialNewTargetCollisions);
}
links.flags |= NodeCheckFlags.TypeChecked;
@@ -23466,7 +23554,7 @@ namespace ts {
}
// Initialize global symbol table
let augmentations: LiteralExpression[][];
let augmentations: ReadonlyArray<StringLiteral>[];
for (const file of host.getSourceFiles()) {
if (!isExternalOrCommonJsModule(file)) {
mergeSymbolTable(globals, file.locals);
+17 -11
View File
@@ -2,6 +2,8 @@
/// <reference path="performance.ts" />
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "2.5";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0`;
@@ -384,6 +386,10 @@ namespace ts {
array.length = outIndex;
}
export function clear(array: {}[]): void {
array.length = 0;
}
export function map<T, U>(array: ReadonlyArray<T>, f: (x: T, i: number) => U): U[] {
let result: U[];
if (array) {
@@ -592,7 +598,7 @@ namespace ts {
return result;
}
export function mapEntries<T, U>(map: Map<T>, f: (key: string, value: T) => [string, U]): Map<U> {
export function mapEntries<T, U>(map: ReadonlyMap<T>, f: (key: string, value: T) => [string, U]): Map<U> {
if (!map) {
return undefined;
}
@@ -1005,9 +1011,9 @@ namespace ts {
* Calls `callback` for each entry in the map, returning the first truthy result.
* Use `map.forEach` instead for normal iteration.
*/
export function forEachEntry<T, U>(map: UnderscoreEscapedMap<T>, callback: (value: T, key: __String) => U | undefined): U | undefined;
export function forEachEntry<T, U>(map: Map<T>, callback: (value: T, key: string) => U | undefined): U | undefined;
export function forEachEntry<T, U>(map: UnderscoreEscapedMap<T> | Map<T>, callback: (value: T, key: (string & __String)) => U | undefined): U | undefined {
export function forEachEntry<T, U>(map: ReadonlyUnderscoreEscapedMap<T>, callback: (value: T, key: __String) => U | undefined): U | undefined;
export function forEachEntry<T, U>(map: ReadonlyMap<T>, callback: (value: T, key: string) => U | undefined): U | undefined;
export function forEachEntry<T, U>(map: ReadonlyUnderscoreEscapedMap<T> | ReadonlyMap<T>, callback: (value: T, key: (string & __String)) => U | undefined): U | undefined {
const iterator = map.entries();
for (let { value: pair, done } = iterator.next(); !done; { value: pair, done } = iterator.next()) {
const [key, value] = pair;
@@ -1020,9 +1026,9 @@ namespace ts {
}
/** `forEachEntry` for just keys. */
export function forEachKey<T>(map: UnderscoreEscapedMap<{}>, callback: (key: __String) => T | undefined): T | undefined;
export function forEachKey<T>(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined;
export function forEachKey<T>(map: UnderscoreEscapedMap<{}> | Map<{}>, callback: (key: string & __String) => T | undefined): T | undefined {
export function forEachKey<T>(map: ReadonlyUnderscoreEscapedMap<{}>, callback: (key: __String) => T | undefined): T | undefined;
export function forEachKey<T>(map: ReadonlyMap<{}>, callback: (key: string) => T | undefined): T | undefined;
export function forEachKey<T>(map: ReadonlyUnderscoreEscapedMap<{}> | ReadonlyMap<{}>, callback: (key: string & __String) => T | undefined): T | undefined {
const iterator = map.keys();
for (let { value: key, done } = iterator.next(); !done; { value: key, done } = iterator.next()) {
const result = callback(key as string & __String);
@@ -1034,8 +1040,8 @@ namespace ts {
}
/** Copy entries from `source` to `target`. */
export function copyEntries<T>(source: UnderscoreEscapedMap<T>, target: UnderscoreEscapedMap<T>): void;
export function copyEntries<T>(source: Map<T>, target: Map<T>): void;
export function copyEntries<T>(source: ReadonlyUnderscoreEscapedMap<T>, target: UnderscoreEscapedMap<T>): void;
export function copyEntries<T>(source: ReadonlyMap<T>, target: Map<T>): void;
export function copyEntries<T, U extends UnderscoreEscapedMap<T> | Map<T>>(source: U, target: U): void {
(source as Map<T>).forEach((value, key) => {
(target as Map<T>).set(key, value);
@@ -1113,8 +1119,8 @@ namespace ts {
}
export function cloneMap(map: SymbolTable): SymbolTable;
export function cloneMap<T>(map: Map<T>): Map<T>;
export function cloneMap<T>(map: Map<T> | SymbolTable): Map<T> | SymbolTable {
export function cloneMap<T>(map: ReadonlyMap<T>): Map<T>;
export function cloneMap<T>(map: ReadonlyMap<T> | SymbolTable): Map<T> | SymbolTable {
const clone = createMap<T>();
copyEntries(map as Map<T>, clone);
return clone;
+6 -6
View File
@@ -211,7 +211,7 @@ namespace ts {
decreaseIndent = newWriter.decreaseIndent;
}
function writeAsynchronousModuleElements(nodes: Node[]) {
function writeAsynchronousModuleElements(nodes: ReadonlyArray<Node>) {
const oldWriter = writer;
forEach(nodes, declaration => {
let nodeToCheck: Node;
@@ -374,13 +374,13 @@ namespace ts {
}
}
function emitLines(nodes: Node[]) {
function emitLines(nodes: ReadonlyArray<Node>) {
for (const node of nodes) {
emit(node);
}
}
function emitSeparatedList(nodes: Node[], separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
function emitSeparatedList(nodes: ReadonlyArray<Node>, separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
let currentWriterPos = writer.getTextPos();
for (const node of nodes) {
if (!canEmitFn || canEmitFn(node)) {
@@ -393,7 +393,7 @@ namespace ts {
}
}
function emitCommaList(nodes: Node[], eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
function emitCommaList(nodes: ReadonlyArray<Node>, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn);
}
@@ -1007,7 +1007,7 @@ namespace ts {
return node.parent.kind === SyntaxKind.MethodDeclaration && hasModifier(node.parent, ModifierFlags.Private);
}
function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) {
function emitTypeParameters(typeParameters: ReadonlyArray<TypeParameterDeclaration>) {
function emitTypeParameter(node: TypeParameterDeclaration) {
increaseIndent();
emitJsDocComments(node);
@@ -1109,7 +1109,7 @@ namespace ts {
}
}
function emitHeritageClause(typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
function emitHeritageClause(typeReferences: ReadonlyArray<ExpressionWithTypeArguments>, isImplementsList: boolean) {
if (typeReferences) {
write(isImplementsList ? " implements " : " extends ");
emitCommaList(typeReferences, emitTypeOfTypeReference);
+1 -1
View File
@@ -2228,7 +2228,7 @@ namespace ts {
* Emits any prologue directives at the start of a Statement list, returning the
* number of prologue directives written to the output.
*/
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean, seenPrologueDirectives?: Map<true>): number {
function emitPrologueDirectives(statements: ReadonlyArray<Node>, startWithNewLine?: boolean, seenPrologueDirectives?: Map<true>): number {
for (let i = 0; i < statements.length; i++) {
const statement = statements[i];
if (isPrologueDirective(statement)) {
+338 -111
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -1121,8 +1121,8 @@ namespace ts {
new TokenConstructor(kind, pos, pos);
}
function createNodeArray<T extends Node>(elements?: T[], pos?: number): NodeArray<T> {
const array = <NodeArray<T>>(elements || []);
function createNodeArray<T extends Node>(elements?: T[], pos?: number): MutableNodeArray<T> {
const array = <MutableNodeArray<T>>(elements || []);
if (!(pos >= 0)) {
pos = getNodePos();
}
@@ -4342,7 +4342,7 @@ namespace ts {
parseExpected(SyntaxKind.OpenParenToken);
node.expression = allowInAnd(parseExpression);
parseExpected(SyntaxKind.CloseParenToken);
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseSpreadElement(): Expression {
@@ -5395,7 +5395,7 @@ namespace ts {
}
function parseDecorators(): NodeArray<Decorator> {
let decorators: NodeArray<Decorator>;
let decorators: NodeArray<Decorator> & Decorator[];
while (true) {
const decoratorStart = getNodePos();
if (!parseOptional(SyntaxKind.AtToken)) {
@@ -5426,7 +5426,7 @@ namespace ts {
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
*/
function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> | undefined {
let modifiers: NodeArray<Modifier> | undefined;
let modifiers: MutableNodeArray<Modifier> | undefined;
while (true) {
const modifierStart = scanner.getStartPos();
const modifierKind = token();
@@ -6165,7 +6165,7 @@ namespace ts {
Debug.assert(start <= end);
Debug.assert(end <= content.length);
let tags: NodeArray<JSDocTag>;
let tags: MutableNodeArray<JSDocTag>;
const comments: string[] = [];
let result: JSDoc;
@@ -6673,9 +6673,9 @@ namespace ts {
const propertyTag = parseParameterOrPropertyTag(atToken, tagName, /*shouldParseParamTag*/ false) as JSDocPropertyTag;
if (propertyTag) {
if (!parentTag.jsDocPropertyTags) {
parentTag.jsDocPropertyTags = <NodeArray<JSDocPropertyTag>>[];
parentTag.jsDocPropertyTags = <MutableNodeArray<JSDocPropertyTag>>[];
}
parentTag.jsDocPropertyTags.push(propertyTag);
(parentTag.jsDocPropertyTags as MutableNodeArray<JSDocPropertyTag>).push(propertyTag);
return true;
}
// Error parsing property tag
+7 -8
View File
@@ -3,7 +3,6 @@
/// <reference path="core.ts" />
namespace ts {
const emptyArray: any[] = [];
const ignoreDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-ignore)?)/;
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string {
@@ -1390,8 +1389,8 @@ namespace ts {
const isExternalModuleFile = isExternalModule(file);
// file.imports may not be undefined if there exists dynamic import
let imports: LiteralExpression[];
let moduleAugmentations: LiteralExpression[];
let imports: StringLiteral[];
let moduleAugmentations: StringLiteral[];
let ambientModules: string[];
// If we are importing helpers, we need to add a synthetic reference to resolve the
@@ -1426,23 +1425,23 @@ namespace ts {
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ExportDeclaration:
const moduleNameExpr = getExternalModuleName(node);
if (!moduleNameExpr || moduleNameExpr.kind !== SyntaxKind.StringLiteral) {
if (!moduleNameExpr || !isStringLiteral(moduleNameExpr)) {
break;
}
if (!(<LiteralExpression>moduleNameExpr).text) {
if (!moduleNameExpr.text) {
break;
}
// TypeScript 1.0 spec (April 2014): 12.1.6
// An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules
// only through top - level external module names. Relative external module names are not permitted.
if (!inAmbientModule || !isExternalModuleNameRelative((<LiteralExpression>moduleNameExpr).text)) {
(imports || (imports = [])).push(<LiteralExpression>moduleNameExpr);
if (!inAmbientModule || !isExternalModuleNameRelative(moduleNameExpr.text)) {
(imports || (imports = [])).push(moduleNameExpr);
}
break;
case SyntaxKind.ModuleDeclaration:
if (isAmbientModule(<ModuleDeclaration>node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) {
const moduleName = <LiteralExpression>(<ModuleDeclaration>node).name;
const moduleName = <StringLiteral>(<ModuleDeclaration>node).name;
// Ambient module declarations can be interpreted as augmentations for some existing external modules.
// This will happen in two cases:
// - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
+1 -1
View File
@@ -492,7 +492,7 @@ namespace ts {
/** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`
*/
function createRestCall(context: TransformationContext, value: Expression, elements: BindingOrAssignmentElement[], computedTempVariables: Expression[], location: TextRange): Expression {
function createRestCall(context: TransformationContext, value: Expression, elements: ReadonlyArray<BindingOrAssignmentElement>, computedTempVariables: ReadonlyArray<Expression>, location: TextRange): Expression {
context.requestEmitHelper(restHelper);
const propertyNames: Expression[] = [];
let computedTempVariableOffset = 0;
+2 -2
View File
@@ -1963,7 +1963,7 @@ namespace ts {
updated,
setTextRange(
createNodeArray(
prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true)
prependCaptureNewTargetIfNeeded(updated.statements as MutableNodeArray<Statement>, node, /*copyOnWrite*/ true)
),
/*location*/ updated.statements
)
@@ -3199,7 +3199,7 @@ namespace ts {
function addStatementToStartOfBlock(block: Block, statement: Statement): Block {
const transformedStatements = visitNodes(block.statements, visitor, isStatement);
return updateBlock(block, [statement].concat(transformedStatements));
return updateBlock(block, [statement, ...transformedStatements]);
}
/**
+1 -1
View File
@@ -156,7 +156,7 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
function chunkObjectLiteralElements(elements: ObjectLiteralElement[]): Expression[] {
function chunkObjectLiteralElements(elements: ReadonlyArray<ObjectLiteralElement>): Expression[] {
let chunkObject: (ShorthandPropertyAssignment | PropertyAssignment)[];
const objects: Expression[] = [];
for (const e of elements) {
+1 -1
View File
@@ -1176,7 +1176,7 @@ namespace ts {
return visitEachChild(node, visitor, context);
}
function transformAndEmitStatements(statements: Statement[], start = 0) {
function transformAndEmitStatements(statements: ReadonlyArray<Statement>, start = 0) {
const numStatements = statements.length;
for (let i = start; i < numStatements; i++) {
transformAndEmitStatement(statements[i]);
+1 -1
View File
@@ -77,7 +77,7 @@ namespace ts {
return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node);
}
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], isChild: boolean, location: TextRange) {
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: ReadonlyArray<JsxChild>, isChild: boolean, location: TextRange) {
const tagName = getTagName(node);
let objectProperties: Expression;
const attrs = node.attributes.properties;
+10 -10
View File
@@ -522,7 +522,7 @@ namespace ts {
return parameter.decorators !== undefined && parameter.decorators.length > 0;
}
function getClassFacts(node: ClassDeclaration, staticProperties: PropertyDeclaration[]) {
function getClassFacts(node: ClassDeclaration, staticProperties: ReadonlyArray<PropertyDeclaration>) {
let facts = ClassFacts.None;
if (some(staticProperties)) facts |= ClassFacts.HasStaticInitializedProperties;
if (getClassExtendsHeritageClauseElement(node)) facts |= ClassFacts.HasExtendsClause;
@@ -1051,7 +1051,7 @@ namespace ts {
*
* @param node The constructor node.
*/
function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ParameterDeclaration[] {
function getParametersWithPropertyAssignments(node: ConstructorDeclaration): ReadonlyArray<ParameterDeclaration> {
return filter(node.parameters, isParameterWithPropertyAssignment);
}
@@ -1104,7 +1104,7 @@ namespace ts {
* @param node The class node.
* @param isStatic A value indicating whether to get properties from the static or instance side of the class.
*/
function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): PropertyDeclaration[] {
function getInitializedProperties(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray<PropertyDeclaration> {
return filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty);
}
@@ -1144,7 +1144,7 @@ namespace ts {
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function addInitializedPropertyStatements(statements: Statement[], properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
function addInitializedPropertyStatements(statements: Statement[], properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
for (const property of properties) {
const statement = createStatement(transformInitializedProperty(property, receiver));
setSourceMapRange(statement, moveRangePastModifiers(property));
@@ -1159,7 +1159,7 @@ namespace ts {
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function generateInitializedPropertyExpressions(properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
function generateInitializedPropertyExpressions(properties: ReadonlyArray<PropertyDeclaration>, receiver: LeftHandSideExpression) {
const expressions: Expression[] = [];
for (const property of properties) {
const expression = transformInitializedProperty(property, receiver);
@@ -1194,7 +1194,7 @@ namespace ts {
* @param isStatic A value indicating whether to retrieve static or instance members of
* the class.
*/
function getDecoratedClassElements(node: ClassExpression | ClassDeclaration, isStatic: boolean): ClassElement[] {
function getDecoratedClassElements(node: ClassExpression | ClassDeclaration, isStatic: boolean): ReadonlyArray<ClassElement> {
return filter(node.members, isStatic ? isStaticDecoratedClassElement : isInstanceDecoratedClassElement);
}
@@ -1233,8 +1233,8 @@ namespace ts {
* A structure describing the decorators for a class element.
*/
interface AllDecorators {
decorators: Decorator[];
parameters?: Decorator[][];
decorators: ReadonlyArray<Decorator>;
parameters?: ReadonlyArray<ReadonlyArray<Decorator>>;
}
/**
@@ -1244,7 +1244,7 @@ namespace ts {
* @param node The function-like node.
*/
function getDecoratorsOfParameters(node: FunctionLikeDeclaration) {
let decorators: Decorator[][];
let decorators: ReadonlyArray<Decorator>[];
if (node) {
const parameters = node.parameters;
for (let i = 0; i < parameters.length; i++) {
@@ -1377,7 +1377,7 @@ namespace ts {
const decoratorExpressions: Expression[] = [];
addRange(decoratorExpressions, map(allDecorators.decorators, transformDecorator));
addRange(decoratorExpressions, flatMap<Decorator[], Expression>(allDecorators.parameters, transformDecoratorsOfParameter));
addRange(decoratorExpressions, flatMap(allDecorators.parameters, transformDecoratorsOfParameter));
addTypeMetadata(node, container, decoratorExpressions);
return decoratorExpressions;
}
+29 -16
View File
@@ -8,13 +8,10 @@ namespace ts {
[index: string]: T;
}
/** ES6 Map interface. */
export interface Map<T> {
/** ES6 Map interface, only read methods included. */
export interface ReadonlyMap<T> {
get(key: string): T | undefined;
has(key: string): boolean;
set(key: string, value: T): this;
delete(key: string): boolean;
clear(): void;
forEach(action: (value: T, key: string) => void): void;
readonly size: number;
keys(): Iterator<string>;
@@ -22,6 +19,13 @@ namespace ts {
entries(): Iterator<[string, T]>;
}
/** ES6 Map interface. */
export interface Map<T> extends ReadonlyMap<T> {
set(key: string, value: T): this;
delete(key: string): boolean;
clear(): void;
}
/** ES6 Iterator type. */
export interface Iterator<T> {
next(): { value: T, done: false } | { value: never, done: true };
@@ -519,7 +523,10 @@ namespace ts {
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
}
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
/* @internal */
export type MutableNodeArray<T extends Node> = NodeArray<T> & T[];
export interface NodeArray<T extends Node> extends ReadonlyArray<T>, TextRange {
hasTrailingComma?: boolean;
/* @internal */ transformFlags?: TransformFlags;
}
@@ -673,7 +680,7 @@ namespace ts {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
name: BindingName; // Declared parameter name
name?: BindingName; // Declared parameter name. Missing if this is a parameter in a JSDocFunctionType.
questionToken?: QuestionToken; // Present on optional parameter
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
@@ -751,7 +758,7 @@ namespace ts {
export interface VariableLikeDeclaration extends NamedDeclaration {
propertyName?: PropertyName;
dotDotDotToken?: DotDotDotToken;
name: DeclarationName;
name?: DeclarationName; // May be missing for ParameterDeclaration, see comment there
questionToken?: QuestionToken;
type?: TypeNode;
initializer?: Expression;
@@ -2314,10 +2321,10 @@ namespace ts {
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
/* @internal */ resolvedModules: Map<ResolvedModuleFull>;
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
/* @internal */ imports: StringLiteral[];
/* @internal */ moduleAugmentations: StringLiteral[];
/* @internal */ imports: ReadonlyArray<StringLiteral>;
/* @internal */ moduleAugmentations: ReadonlyArray<StringLiteral>;
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
/* @internal */ ambientModuleNames: string[];
/* @internal */ ambientModuleNames: ReadonlyArray<string>;
/* @internal */ checkJsDirective: CheckJsDirective | undefined;
}
@@ -2520,6 +2527,7 @@ namespace ts {
* Returns `any` if the index is not valid.
*/
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
getNullableType(type: Type, flags: TypeFlags): Type;
getNonNullableType(type: Type): Type;
/** Note that the resulting nodes cannot be checked. */
@@ -2677,6 +2685,7 @@ namespace ts {
SuppressAnyReturnType = 1 << 12, // If the return type is any-like, don't offer a return type.
AddUndefined = 1 << 13, // Add undefined to types of initialized, non-optional parameters
WriteClassExpressionAsTypeLiteral = 1 << 14, // Write a type literal instead of (Anonymous class)
InArrayType = 1 << 15, // Writing an array element type
}
export const enum SymbolFormatFlags {
@@ -2982,13 +2991,10 @@ namespace ts {
*/
export type __String = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }) | InternalSymbolName;
/** EscapedStringMap based on ES6 Map interface. */
export interface UnderscoreEscapedMap<T> {
/** ReadonlyMap where keys are `__String`s. */
export interface ReadonlyUnderscoreEscapedMap<T> {
get(key: __String): T | undefined;
has(key: __String): boolean;
set(key: __String, value: T): this;
delete(key: __String): boolean;
clear(): void;
forEach(action: (value: T, key: __String) => void): void;
readonly size: number;
keys(): Iterator<__String>;
@@ -2996,6 +3002,13 @@ namespace ts {
entries(): Iterator<[__String, T]>;
}
/** Map where keys are `__String`s. */
export interface UnderscoreEscapedMap<T> extends ReadonlyUnderscoreEscapedMap<T> {
set(key: __String, value: T): this;
delete(key: __String): boolean;
clear(): void;
}
/** SymbolTable based on ES6 Map interface. */
export type SymbolTable = UnderscoreEscapedMap<Symbol>;
+7 -24
View File
@@ -640,7 +640,8 @@ namespace ts {
const commentRanges = (node.kind === SyntaxKind.Parameter ||
node.kind === SyntaxKind.TypeParameter ||
node.kind === SyntaxKind.FunctionExpression ||
node.kind === SyntaxKind.ArrowFunction) ?
node.kind === SyntaxKind.ArrowFunction ||
node.kind === SyntaxKind.ParenthesizedExpression) ?
concatenate(getTrailingCommentRanges(text, node.pos), getLeadingCommentRanges(text, node.pos)) :
getLeadingCommentRangesOfNodeFromText(node, text);
// True if the comment starts with '/**' but not if it is '/**/'
@@ -1539,27 +1540,9 @@ namespace ts {
}
export function getJSDocParameterTags(param: ParameterDeclaration): JSDocParameterTag[] | undefined {
const func = param.parent;
const tags = getJSDocTags(func);
if (!tags) return undefined;
if (!param.name) {
// this is an anonymous jsdoc param from a `function(type1, type2): type3` specification
const paramIndex = func.parameters.indexOf(param);
Debug.assert(paramIndex !== -1);
let curParamIndex = 0;
for (const tag of tags) {
if (isJSDocParameterTag(tag)) {
if (curParamIndex === paramIndex) {
return [tag];
}
curParamIndex++;
}
}
}
else if (param.name.kind === SyntaxKind.Identifier) {
const name = (param.name as Identifier).text;
return tags.filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && tag.name.text === name) as JSDocParameterTag[];
if (param.name && isIdentifier(param.name)) {
const name = param.name.text;
return getJSDocTags(param.parent).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && tag.name.text === name) as JSDocParameterTag[];
}
else {
// TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines
@@ -2748,7 +2731,7 @@ namespace ts {
* Gets the effective type parameters. If the node was parsed in a
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
*/
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): TypeParameterDeclaration[] {
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray<TypeParameterDeclaration> {
if (node.typeParameters) {
return node.typeParameters;
}
@@ -4756,7 +4739,7 @@ namespace ts {
// Node Arrays
/* @internal */
export function isNodeArray<T extends Node>(array: T[]): array is NodeArray<T> {
export function isNodeArray<T extends Node>(array: ReadonlyArray<T>): array is NodeArray<T> {
return array.hasOwnProperty("pos")
&& array.hasOwnProperty("end");
}
+6 -6
View File
@@ -86,7 +86,7 @@ namespace ts {
return nodes;
}
let updated: NodeArray<T>;
let updated: MutableNodeArray<T>;
// Ensure start and count have valid values
const length = nodes.length;
@@ -901,7 +901,7 @@ namespace ts {
*
* @param nodes The NodeArray.
*/
function extractSingleNode(nodes: Node[]): Node {
function extractSingleNode(nodes: ReadonlyArray<Node>): Node {
Debug.assert(nodes.length <= 1, "Too many nodes written to output.");
return singleOrUndefined(nodes);
}
@@ -1421,13 +1421,13 @@ namespace ts {
/**
* Merges generated lexical declarations into a new statement list.
*/
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: Statement[]): NodeArray<Statement>;
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: ReadonlyArray<Statement>): NodeArray<Statement>;
/**
* Appends generated lexical declarations to an array of statements.
*/
export function mergeLexicalEnvironment(statements: Statement[], declarations: Statement[]): Statement[];
export function mergeLexicalEnvironment(statements: Statement[], declarations: Statement[]) {
export function mergeLexicalEnvironment(statements: Statement[], declarations: ReadonlyArray<Statement>): Statement[];
export function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: ReadonlyArray<Statement>) {
if (!some(declarations)) {
return statements;
}
@@ -1442,7 +1442,7 @@ namespace ts {
*
* @param nodes The NodeArray.
*/
export function liftToBlock(nodes: Node[]): Statement {
export function liftToBlock(nodes: ReadonlyArray<Node>): Statement {
Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block.");
return <Statement>singleOrUndefined(nodes) || createBlock(<NodeArray<Statement>>nodes);
}
+1 -1
View File
@@ -130,7 +130,7 @@ namespace FourSlash {
// 0 - cancelled
// >0 - not cancelled
// <0 - not cancelled and value denotes number of isCancellationRequested after which token become cancelled
private static NotCanceled: number = -1;
private static readonly NotCanceled: number = -1;
private numberOfCallsBeforeCancellation: number = TestCancellationToken.NotCanceled;
public isCancellationRequested(): boolean {
+1 -1
View File
@@ -108,7 +108,7 @@ namespace Harness.LanguageService {
}
class DefaultHostCancellationToken implements ts.HostCancellationToken {
public static Instance = new DefaultHostCancellationToken();
public static readonly Instance = new DefaultHostCancellationToken();
public isCancellationRequested() {
return false;
+1 -3
View File
@@ -238,10 +238,8 @@ namespace RWC {
}
class RWCRunner extends RunnerBase {
private static sourcePath = "internal/cases/rwc/";
public enumerateTestFiles() {
return Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
return Harness.IO.listFiles("internal/cases/rwc/", /.+\.json$/);
}
public kind(): TestRunnerKind {
+6 -6
View File
@@ -4,19 +4,19 @@
/* tslint:disable:no-null-keyword */
class Test262BaselineRunner extends RunnerBase {
private static basePath = "internal/cases/test262";
private static helpersFilePath = "tests/cases/test262-harness/helpers.d.ts";
private static helperFile: Harness.Compiler.TestFile = {
private static readonly basePath = "internal/cases/test262";
private static readonly helpersFilePath = "tests/cases/test262-harness/helpers.d.ts";
private static readonly helperFile: Harness.Compiler.TestFile = {
unitName: Test262BaselineRunner.helpersFilePath,
content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath),
};
private static testFileExtensionRegex = /\.js$/;
private static options: ts.CompilerOptions = {
private static readonly testFileExtensionRegex = /\.js$/;
private static readonly options: ts.CompilerOptions = {
allowNonTsExtensions: true,
target: ts.ScriptTarget.Latest,
module: ts.ModuleKind.CommonJS
};
private static baselineOptions: Harness.Baseline.BaselineOptions = {
private static readonly baselineOptions: Harness.Baseline.BaselineOptions = {
Subfolder: "test262",
Baselinefolder: "internal/baselines"
};
+3 -3
View File
@@ -67,12 +67,12 @@ namespace ts {
}
function flattenNodes(n: Node) {
const data: (Node | NodeArray<any>)[] = [];
const data: (Node | NodeArray<Node>)[] = [];
walk(n);
return data;
function walk(n: Node | Node[]): void {
data.push(<any>n);
function walk(n: Node | NodeArray<Node>): void {
data.push(n);
return isArray(n) ? forEach(n, walk) : forEachChild(n, walk, walk);
}
}
@@ -704,7 +704,7 @@ namespace ts.projectSystem {
}
clearOutput() {
this.output.length = 0;
clear(this.output);
}
readonly readFile = (s: string) => (<File>this.fs.get(this.toFullPath(s))).content;
+1 -1
View File
@@ -223,7 +223,7 @@ namespace ts.server {
for (const reference of this.references) {
reference.removeReferencedBy(this);
}
this.references = createSortedArray<ModuleBuilderFileInfo>();
clear(this.references);
}
}
+5 -8
View File
@@ -225,10 +225,7 @@ namespace ts.server {
const fileNamePropertyReader: FilePropertyReader<string> = {
getFileName: x => x,
getScriptKind: _ => undefined,
hasMixedContent: (fileName, extraFileExtensions) => {
const mixedContentExtensions = map(filter(extraFileExtensions, item => item.isMixedContent), item => item.extension);
return forEach(mixedContentExtensions, extension => fileExtensionIs(fileName, extension));
}
hasMixedContent: (fileName, extraFileExtensions) => some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)),
};
const externalFilePropertyReader: FilePropertyReader<protocol.ExternalFile> = {
@@ -725,7 +722,7 @@ namespace ts.server {
switch (project.projectKind) {
case ProjectKind.External:
removeItemFromSet(this.externalProjects, <ExternalProject>project);
unorderedRemoveItem(this.externalProjects, <ExternalProject>project);
this.projectToSizeMap.delete((project as ExternalProject).externalProjectName);
break;
case ProjectKind.Configured:
@@ -734,7 +731,7 @@ namespace ts.server {
this.setConfigFilePresenceByClosedConfigFile(<ConfiguredProject>project);
break;
case ProjectKind.Inferred:
removeItemFromSet(this.inferredProjects, <InferredProject>project);
unorderedRemoveItem(this.inferredProjects, <InferredProject>project);
break;
}
}
@@ -793,7 +790,7 @@ namespace ts.server {
info.close();
this.stopWatchingConfigFilesForClosedScriptInfo(info);
removeItemFromSet(this.openFiles, info);
unorderedRemoveItem(this.openFiles, info);
// collect all projects that should be removed
let projectsToRemove: Project[];
@@ -1896,7 +1893,7 @@ namespace ts.server {
}
/** Makes a filename safe to insert in a RegExp */
private static filenameEscapeRegexp = /[-\/\\^$*+?.()|[\]{}]/g;
private static readonly filenameEscapeRegexp = /[-\/\\^$*+?.()|[\]{}]/g;
private static escapeFilenameForRegex(filename: string) {
return filename.replace(this.filenameEscapeRegexp, "\\$&");
}
+1 -1
View File
@@ -876,7 +876,7 @@ namespace ts.server {
*/
export class InferredProject extends Project {
private static newName = (() => {
private static readonly newName = (() => {
let nextId = 1;
return () => {
const id = nextId;
+2 -2
View File
@@ -232,7 +232,7 @@ namespace ts.server {
}
break;
default:
removeItemFromSet(this.containingProjects, project);
unorderedRemoveItem(this.containingProjects, project);
break;
}
}
@@ -251,7 +251,7 @@ namespace ts.server {
p.addMissingFileRoot(this.fileName);
}
}
this.containingProjects.length = 0;
clear(this.containingProjects);
}
getDefaultProject() {
+5 -11
View File
@@ -162,19 +162,13 @@ namespace ts.server {
* Represents operation that can schedule its next step to be executed later.
* Scheduling is done via instance of NextStep. If on current step subsequent step was not scheduled - operation is assumed to be completed.
*/
class MultistepOperation {
class MultistepOperation implements NextStep {
private requestId: number;
private timerHandle: any;
private immediateId: any;
private completed = true;
private readonly next: NextStep;
constructor(private readonly operationHost: MultistepOperationHost) {
this.next = {
immediate: action => this.immediate(action),
delay: (ms, action) => this.delay(ms, action)
};
}
constructor(private readonly operationHost: MultistepOperationHost) {}
public startNew(action: (next: NextStep) => void) {
this.complete();
@@ -194,7 +188,7 @@ namespace ts.server {
this.setImmediateId(undefined);
}
private immediate(action: () => void) {
public immediate(action: () => void) {
const requestId = this.requestId;
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "immediate: incorrect request id");
this.setImmediateId(this.operationHost.getServerHost().setImmediate(() => {
@@ -203,7 +197,7 @@ namespace ts.server {
}));
}
private delay(ms: number, action: () => void) {
public delay(ms: number, action: () => void) {
const requestId = this.requestId;
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "delay: incorrect request id");
this.setTimerHandle(this.operationHost.getServerHost().setTimeout(() => {
@@ -219,7 +213,7 @@ namespace ts.server {
stop = true;
}
else {
action(this.next);
action(this);
}
}
catch (e) {
-18
View File
@@ -103,24 +103,6 @@ namespace ts.server {
}
}
export function removeItemFromSet<T>(items: T[], itemToRemove: T) {
if (items.length === 0) {
return;
}
const index = items.indexOf(itemToRemove);
if (index < 0) {
return;
}
if (index === items.length - 1) {
// last item - pop it
items.pop();
}
else {
// non-last item - replace it with the last one
items[index] = items.pop();
}
}
export type NormalizedPath = string & { __normalizedPathTag: any };
export function toNormalizedPath(fileName: string): NormalizedPath {
@@ -32,7 +32,7 @@ namespace ts.codefix {
}
}
// If all fails, add an extra new line immediatlly before the error span.
// If all fails, add an extra new line immediately before the error span.
return {
span: { start: position, length: 0 },
newText: `${position === startPosition ? "" : newLineCharacter}// @ts-ignore${newLineCharacter}`
@@ -67,4 +67,4 @@ namespace ts.codefix {
}]
}];
}
}
}
+40
View File
@@ -0,0 +1,40 @@
/* @internal */
namespace ts.codefix {
registerCodeFix({
errorCodes: [Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments.code],
getCodeActions: getActionsForJSDocTypes
});
function getActionsForJSDocTypes(context: CodeFixContext): CodeAction[] | undefined {
const sourceFile = context.sourceFile;
const node = getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false);
const decl = ts.findAncestor(node, n => n.kind === SyntaxKind.VariableDeclaration);
if (!decl) return;
const checker = context.program.getTypeChecker();
const jsdocType = (decl as VariableDeclaration).type;
const original = getTextOfNode(jsdocType);
const type = checker.getTypeFromTypeNode(jsdocType);
const actions = [createAction(jsdocType, sourceFile.fileName, original, checker.typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTruncation))];
if (jsdocType.kind === SyntaxKind.JSDocNullableType) {
// for nullable types, suggest the flow-compatible `T | null | undefined`
// in addition to the jsdoc/closure-compatible `T | null`
const replacementWithUndefined = checker.typeToString(checker.getNullableType(type, TypeFlags.Undefined), /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTruncation);
actions.push(createAction(jsdocType, sourceFile.fileName, original, replacementWithUndefined));
}
return actions;
}
function createAction(declaration: TypeNode, fileName: string, original: string, replacement: string): CodeAction {
return {
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Change_0_to_1), [original, replacement]),
changes: [{
fileName,
textChanges: [{
span: { start: declaration.getStart(), length: declaration.getWidth() },
newText: replacement
}]
}],
};
}
}
+1
View File
@@ -7,6 +7,7 @@
/// <reference path="fixExtendsInterfaceBecomesImplements.ts" />
/// <reference path="fixForgottenThisPropertyAccess.ts" />
/// <reference path='fixUnusedIdentifier.ts' />
/// <reference path='fixJSDocTypes.ts' />
/// <reference path='importFixes.ts' />
/// <reference path='disableJsDiagnostics.ts' />
/// <reference path='helpers.ts' />
+8 -2
View File
@@ -186,7 +186,7 @@ namespace ts.codefix {
return parameters;
}
function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, optional: boolean, modifiers: Modifier[] | undefined): MethodDeclaration {
function createMethodImplementingSignatures(signatures: ReadonlyArray<Signature>, name: PropertyName, optional: boolean, modifiers: ReadonlyArray<Modifier> | undefined): MethodDeclaration {
/** This is *a* signature with the maximal number of arguments,
* such that if there is a "maximal" signature without rest arguments,
* this is one of them.
@@ -231,7 +231,13 @@ namespace ts.codefix {
/*returnType*/ undefined);
}
export function createStubbedMethod(modifiers: Modifier[], name: PropertyName, optional: boolean, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], returnType: TypeNode | undefined) {
export function createStubbedMethod(
modifiers: ReadonlyArray<Modifier>,
name: PropertyName,
optional: boolean,
typeParameters: ReadonlyArray<TypeParameterDeclaration> | undefined,
parameters: ReadonlyArray<ParameterDeclaration>,
returnType: TypeNode | undefined) {
return createMethod(
/*decorators*/ undefined,
modifiers,
+23 -11
View File
@@ -963,7 +963,7 @@ namespace ts.Completions {
isMemberCompletion = true;
let typeMembers: Symbol[];
let existingMembers: Declaration[];
let existingMembers: ReadonlyArray<Declaration>;
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
// We are completing on contextual types, but may also include properties
@@ -1093,14 +1093,14 @@ namespace ts.Completions {
}
}
const implementedInterfaceTypePropertySymbols = (classElementModifierFlags & ModifierFlags.Static) ?
undefined :
flatMap(implementsTypeNodes, typeNode => typeChecker.getPropertiesOfType(typeChecker.getTypeAtLocation(typeNode)));
emptyArray :
flatMap(implementsTypeNodes || emptyArray, typeNode => typeChecker.getPropertiesOfType(typeChecker.getTypeAtLocation(typeNode)));
// List of property symbols of base type that are not private and already implemented
symbols = filterClassMembersList(
baseClassTypeToGetPropertiesFrom ?
typeChecker.getPropertiesOfType(baseClassTypeToGetPropertiesFrom) :
undefined,
emptyArray,
implementedInterfaceTypePropertySymbols,
classLikeDeclaration.members,
classElementModifierFlags);
@@ -1443,7 +1443,7 @@ namespace ts.Completions {
* @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports
* do not occur at the current position and have not otherwise been typed.
*/
function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] {
function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ReadonlyArray<ImportOrExportSpecifier>): Symbol[] {
const existingImportsOrExports = createUnderscoreEscapedMap<boolean>();
for (const element of namedImportsOrExports) {
@@ -1469,7 +1469,7 @@ namespace ts.Completions {
* @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations
* do not occur at the current position and have not otherwise been typed.
*/
function filterObjectMembersList(contextualMemberSymbols: Symbol[], existingMembers: Declaration[]): Symbol[] {
function filterObjectMembersList(contextualMemberSymbols: Symbol[], existingMembers: ReadonlyArray<Declaration>): Symbol[] {
if (!existingMembers || existingMembers.length === 0) {
return contextualMemberSymbols;
}
@@ -1518,7 +1518,11 @@ namespace ts.Completions {
*
* @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags
*/
function filterClassMembersList(baseSymbols: Symbol[], implementingTypeSymbols: Symbol[], existingMembers: ClassElement[], currentClassElementModifierFlags: ModifierFlags): Symbol[] {
function filterClassMembersList(
baseSymbols: ReadonlyArray<Symbol>,
implementingTypeSymbols: ReadonlyArray<Symbol>,
existingMembers: ReadonlyArray<ClassElement>,
currentClassElementModifierFlags: ModifierFlags): Symbol[] {
const existingMemberNames = createUnderscoreEscapedMap<boolean>();
for (const m of existingMembers) {
// Ignore omitted expressions for missing members
@@ -1553,10 +1557,18 @@ namespace ts.Completions {
}
}
return concatenate(
filter(baseSymbols, baseProperty => isValidProperty(baseProperty, ModifierFlags.Private)),
filter(implementingTypeSymbols, implementingProperty => isValidProperty(implementingProperty, ModifierFlags.NonPublicAccessibilityModifier))
);
const result: Symbol[] = [];
addPropertySymbols(baseSymbols, ModifierFlags.Private);
addPropertySymbols(implementingTypeSymbols, ModifierFlags.NonPublicAccessibilityModifier);
return result;
function addPropertySymbols(properties: ReadonlyArray<Symbol>, inValidModifierFlags: ModifierFlags) {
for (const property of properties) {
if (isValidProperty(property, inValidModifierFlags)) {
result.push(property);
}
}
}
function isValidProperty(propertySymbol: Symbol, inValidModifierFlags: ModifierFlags) {
return !existingMemberNames.get(propertySymbol.name) &&
+5 -6
View File
@@ -298,21 +298,20 @@ namespace ts.DocumentHighlights {
const keywords: Node[] = [];
const modifierFlag: ModifierFlags = getFlagFromModifier(modifier);
let nodes: Node[];
let nodes: ReadonlyArray<Node>;
switch (container.kind) {
case SyntaxKind.ModuleBlock:
case SyntaxKind.SourceFile:
// Container is either a class declaration or the declaration is a classDeclaration
if (modifierFlag & ModifierFlags.Abstract) {
nodes = (<Node[]>(<ClassDeclaration>declaration).members).concat(declaration);
nodes = [...(<ClassDeclaration>declaration).members, declaration];
}
else {
nodes = (<Block>container).statements;
}
break;
case SyntaxKind.Constructor:
nodes = (<Node[]>(<ConstructorDeclaration>container).parameters).concat(
(<ClassDeclaration>container.parent).members);
nodes = [...(<ConstructorDeclaration>container).parameters, ...(<ClassDeclaration>container.parent).members];
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
@@ -326,11 +325,11 @@ namespace ts.DocumentHighlights {
});
if (constructor) {
nodes = nodes.concat(constructor.parameters);
nodes = [...nodes, ...constructor.parameters];
}
}
else if (modifierFlag & ModifierFlags.Abstract) {
nodes = nodes.concat(container);
nodes = [...nodes, container];
}
break;
default:
+1 -1
View File
@@ -1152,7 +1152,7 @@ namespace ts.formatting {
}
}
function getOpenTokenForList(node: Node, list: Node[]) {
function getOpenTokenForList(node: Node, list: ReadonlyArray<Node>) {
switch (node.kind) {
case SyntaxKind.Constructor:
case SyntaxKind.FunctionDeclaration:
@@ -4,13 +4,13 @@
namespace ts.formatting {
export class RuleOperationContext {
private customContextChecks: { (context: FormattingContext): boolean; }[];
private readonly customContextChecks: { (context: FormattingContext): boolean; }[];
constructor(...funcs: { (context: FormattingContext): boolean; }[]) {
this.customContextChecks = funcs;
}
static Any: RuleOperationContext = new RuleOperationContext();
static readonly Any: RuleOperationContext = new RuleOperationContext();
public IsAny(): boolean {
return this === RuleOperationContext.Any;
+2 -2
View File
@@ -328,7 +328,7 @@ namespace ts.formatting {
const containingList = getContainingList(node, sourceFile);
return containingList ? getActualIndentationFromList(containingList) : Value.Unknown;
function getActualIndentationFromList(list: Node[]): number {
function getActualIndentationFromList(list: ReadonlyArray<Node>): number {
const index = indexOf(list, node);
return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : Value.Unknown;
}
@@ -378,7 +378,7 @@ namespace ts.formatting {
}
}
function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: EditorSettings): number {
function deriveActualIndentationFromList(list: ReadonlyArray<Node>, index: number, sourceFile: SourceFile, options: EditorSettings): number {
Debug.assert(index >= 0 && index < list.length);
const node = list[index];
+1 -1
View File
@@ -191,7 +191,7 @@ namespace ts.GoToDefinition {
return false;
}
function tryAddSignature(signatureDeclarations: Declaration[] | undefined, selectConstructors: boolean, symbolKind: ScriptElementKind, symbolName: string, containerName: string, result: DefinitionInfo[]) {
function tryAddSignature(signatureDeclarations: ReadonlyArray<Declaration> | undefined, selectConstructors: boolean, symbolKind: ScriptElementKind, symbolName: string, containerName: string, result: DefinitionInfo[]) {
if (!signatureDeclarations) {
return false;
}
+2 -2
View File
@@ -241,7 +241,7 @@ namespace ts.JsDoc {
return { newText: result, caretOffset: preamble.length };
}
function getParametersForJsDocOwningNode(commentOwner: Node): ParameterDeclaration[] {
function getParametersForJsDocOwningNode(commentOwner: Node): ReadonlyArray<ParameterDeclaration> {
if (isFunctionLike(commentOwner)) {
return commentOwner.parameters;
}
@@ -266,7 +266,7 @@ namespace ts.JsDoc {
* @param rightHandSide the expression which may contain an appropriate set of parameters
* @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'.
*/
function getParametersFromRightHandSideOfAssignment(rightHandSide: Expression): ParameterDeclaration[] {
function getParametersFromRightHandSideOfAssignment(rightHandSide: Expression): ReadonlyArray<ParameterDeclaration> {
while (rightHandSide.kind === SyntaxKind.ParenthesizedExpression) {
rightHandSide = (<ParenthesizedExpression>rightHandSide).expression;
}
+1 -1
View File
@@ -1176,7 +1176,7 @@ namespace ts {
public close(): void {
// Forget all the registered shims
this._shims = [];
clear(this._shims);
this.documentRegistry = undefined;
}
-2
View File
@@ -1,8 +1,6 @@
///<reference path='services.ts' />
/* @internal */
namespace ts.SignatureHelp {
const emptyArray: any[] = [];
export const enum ArgumentListKind {
TypeArguments,
CallArguments,
@@ -18,13 +18,13 @@ interface IHasVisualizationModel {
var xs: IHasVisualizationModel[] = [moduleA];
>xs : IHasVisualizationModel[]
>IHasVisualizationModel : IHasVisualizationModel
>[moduleA] : typeof moduleA[]
>[moduleA] : (typeof moduleA)[]
>moduleA : typeof moduleA
var xs2: typeof moduleA[] = [moduleA];
>xs2 : typeof moduleA[]
>xs2 : (typeof moduleA)[]
>moduleA : typeof moduleA
>[moduleA] : typeof moduleA[]
>[moduleA] : (typeof moduleA)[]
>moduleA : typeof moduleA
=== tests/cases/compiler/aliasUsageInArray_backbone.ts ===
@@ -22,8 +22,8 @@ class C {
>foo : string
}
var y = [C, C];
>y : typeof C[]
>[C, C] : typeof C[]
>y : (typeof C)[]
>[C, C] : (typeof C)[]
>C : typeof C
>C : typeof C
@@ -31,7 +31,7 @@ var r3 = new y[0]();
>r3 : C
>new y[0]() : C
>y[0] : typeof C
>y : typeof C[]
>y : (typeof C)[]
>0 : 0
var a: { (x: number): number; (x: string): string; };
@@ -0,0 +1,28 @@
=== tests/cases/conformance/types/thisType/context.js ===
const obj = {
>obj : Symbol(obj, Decl(context.js, 0, 5))
prop: 2,
>prop : Symbol(prop, Decl(context.js, 0, 13))
method() {
>method : Symbol(method, Decl(context.js, 1, 12))
this;
>this : Symbol(obj, Decl(context.js, 0, 11))
this.prop;
>this.prop : Symbol(prop, Decl(context.js, 0, 13))
>this : Symbol(obj, Decl(context.js, 0, 11))
>prop : Symbol(prop, Decl(context.js, 0, 13))
this.method;
>this.method : Symbol(method, Decl(context.js, 1, 12))
>this : Symbol(obj, Decl(context.js, 0, 11))
>method : Symbol(method, Decl(context.js, 1, 12))
this.unknown; // ok, obj has a string indexer
>this : Symbol(obj, Decl(context.js, 0, 11))
}
}
@@ -0,0 +1,32 @@
=== tests/cases/conformance/types/thisType/context.js ===
const obj = {
>obj : { [x: string]: any; prop: number; method(): void; }
>{ prop: 2, method() { this; this.prop; this.method; this.unknown; // ok, obj has a string indexer }} : { [x: string]: any; prop: number; method(): void; }
prop: 2,
>prop : number
>2 : 2
method() {
>method : () => void
this;
>this : { [x: string]: any; prop: number; method(): void; }
this.prop;
>this.prop : number
>this : { [x: string]: any; prop: number; method(): void; }
>prop : number
this.method;
>this.method : () => void
>this : { [x: string]: any; prop: number; method(): void; }
>method : () => void
this.unknown; // ok, obj has a string indexer
>this.unknown : any
>this : { [x: string]: any; prop: number; method(): void; }
>unknown : any
}
}
@@ -1,16 +1,16 @@
=== tests/cases/compiler/declarationEmitIndexTypeArray.ts ===
function doSomethingWithKeys<T>(...keys: (keyof T)[]) { }
>doSomethingWithKeys : <T>(...keys: keyof T[]) => void
>doSomethingWithKeys : <T>(...keys: (keyof T)[]) => void
>T : T
>keys : keyof T[]
>keys : (keyof T)[]
>T : T
const utilityFunctions = {
>utilityFunctions : { doSomethingWithKeys: <T>(...keys: keyof T[]) => void; }
>{ doSomethingWithKeys} : { doSomethingWithKeys: <T>(...keys: keyof T[]) => void; }
>utilityFunctions : { doSomethingWithKeys: <T>(...keys: (keyof T)[]) => void; }
>{ doSomethingWithKeys} : { doSomethingWithKeys: <T>(...keys: (keyof T)[]) => void; }
doSomethingWithKeys
>doSomethingWithKeys : <T>(...keys: keyof T[]) => void
>doSomethingWithKeys : <T>(...keys: (keyof T)[]) => void
};
@@ -0,0 +1,57 @@
//// [destructuringTypeGuardFlow.ts]
type foo = {
bar: number | null;
baz: string;
nested: {
a: number;
b: string | null;
}
};
const aFoo: foo = { bar: 3, baz: "b", nested: { a: 1, b: "y" } };
if (aFoo.bar && aFoo.nested.b) {
const { bar, baz, nested: {a, b: text} } = aFoo;
const right: number = aFoo.bar;
const wrong: number = bar;
const another: string = baz;
const aAgain: number = a;
const bAgain: string = text;
}
type bar = {
elem1: number | null;
elem2: foo | null;
};
const bBar = { elem1: 7, elem2: aFoo };
if (bBar.elem2 && bBar.elem2.bar && bBar.elem2.nested.b) {
const { bar, baz, nested: {a, b: text} } = bBar.elem2;
const right: number = bBar.elem2.bar;
const wrong: number = bar;
const another: string = baz;
const aAgain: number = a;
const bAgain: string = text;
}
//// [destructuringTypeGuardFlow.js]
var aFoo = { bar: 3, baz: "b", nested: { a: 1, b: "y" } };
if (aFoo.bar && aFoo.nested.b) {
var bar = aFoo.bar, baz = aFoo.baz, _a = aFoo.nested, a = _a.a, text = _a.b;
var right = aFoo.bar;
var wrong = bar;
var another = baz;
var aAgain = a;
var bAgain = text;
}
var bBar = { elem1: 7, elem2: aFoo };
if (bBar.elem2 && bBar.elem2.bar && bBar.elem2.nested.b) {
var _b = bBar.elem2, bar = _b.bar, baz = _b.baz, _c = _b.nested, a = _c.a, text = _c.b;
var right = bBar.elem2.bar;
var wrong = bar;
var another = baz;
var aAgain = a;
var bAgain = text;
}
@@ -0,0 +1,143 @@
=== tests/cases/compiler/destructuringTypeGuardFlow.ts ===
type foo = {
>foo : Symbol(foo, Decl(destructuringTypeGuardFlow.ts, 0, 0))
bar: number | null;
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
baz: string;
>baz : Symbol(baz, Decl(destructuringTypeGuardFlow.ts, 1, 21))
nested: {
>nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 2, 14))
a: number;
>a : Symbol(a, Decl(destructuringTypeGuardFlow.ts, 3, 11))
b: string | null;
>b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 4, 14))
}
};
const aFoo: foo = { bar: 3, baz: "b", nested: { a: 1, b: "y" } };
>aFoo : Symbol(aFoo, Decl(destructuringTypeGuardFlow.ts, 9, 5))
>foo : Symbol(foo, Decl(destructuringTypeGuardFlow.ts, 0, 0))
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 9, 19))
>baz : Symbol(baz, Decl(destructuringTypeGuardFlow.ts, 9, 27))
>nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 9, 37))
>a : Symbol(a, Decl(destructuringTypeGuardFlow.ts, 9, 47))
>b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 9, 53))
if (aFoo.bar && aFoo.nested.b) {
>aFoo.bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
>aFoo : Symbol(aFoo, Decl(destructuringTypeGuardFlow.ts, 9, 5))
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
>aFoo.nested.b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 4, 14))
>aFoo.nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 2, 14))
>aFoo : Symbol(aFoo, Decl(destructuringTypeGuardFlow.ts, 9, 5))
>nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 2, 14))
>b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 4, 14))
const { bar, baz, nested: {a, b: text} } = aFoo;
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 12, 9))
>baz : Symbol(baz, Decl(destructuringTypeGuardFlow.ts, 12, 14))
>nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 2, 14))
>a : Symbol(a, Decl(destructuringTypeGuardFlow.ts, 12, 29))
>b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 4, 14))
>text : Symbol(text, Decl(destructuringTypeGuardFlow.ts, 12, 31))
>aFoo : Symbol(aFoo, Decl(destructuringTypeGuardFlow.ts, 9, 5))
const right: number = aFoo.bar;
>right : Symbol(right, Decl(destructuringTypeGuardFlow.ts, 13, 7))
>aFoo.bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
>aFoo : Symbol(aFoo, Decl(destructuringTypeGuardFlow.ts, 9, 5))
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
const wrong: number = bar;
>wrong : Symbol(wrong, Decl(destructuringTypeGuardFlow.ts, 14, 7))
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 12, 9))
const another: string = baz;
>another : Symbol(another, Decl(destructuringTypeGuardFlow.ts, 15, 7))
>baz : Symbol(baz, Decl(destructuringTypeGuardFlow.ts, 12, 14))
const aAgain: number = a;
>aAgain : Symbol(aAgain, Decl(destructuringTypeGuardFlow.ts, 16, 7))
>a : Symbol(a, Decl(destructuringTypeGuardFlow.ts, 12, 29))
const bAgain: string = text;
>bAgain : Symbol(bAgain, Decl(destructuringTypeGuardFlow.ts, 17, 7))
>text : Symbol(text, Decl(destructuringTypeGuardFlow.ts, 12, 31))
}
type bar = {
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 18, 1))
elem1: number | null;
>elem1 : Symbol(elem1, Decl(destructuringTypeGuardFlow.ts, 20, 12))
elem2: foo | null;
>elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 21, 23))
>foo : Symbol(foo, Decl(destructuringTypeGuardFlow.ts, 0, 0))
};
const bBar = { elem1: 7, elem2: aFoo };
>bBar : Symbol(bBar, Decl(destructuringTypeGuardFlow.ts, 25, 5))
>elem1 : Symbol(elem1, Decl(destructuringTypeGuardFlow.ts, 25, 14))
>elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>aFoo : Symbol(aFoo, Decl(destructuringTypeGuardFlow.ts, 9, 5))
if (bBar.elem2 && bBar.elem2.bar && bBar.elem2.nested.b) {
>bBar.elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bBar : Symbol(bBar, Decl(destructuringTypeGuardFlow.ts, 25, 5))
>elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bBar.elem2.bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
>bBar.elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bBar : Symbol(bBar, Decl(destructuringTypeGuardFlow.ts, 25, 5))
>elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
>bBar.elem2.nested.b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 4, 14))
>bBar.elem2.nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 2, 14))
>bBar.elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bBar : Symbol(bBar, Decl(destructuringTypeGuardFlow.ts, 25, 5))
>elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 2, 14))
>b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 4, 14))
const { bar, baz, nested: {a, b: text} } = bBar.elem2;
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 28, 9))
>baz : Symbol(baz, Decl(destructuringTypeGuardFlow.ts, 28, 14))
>nested : Symbol(nested, Decl(destructuringTypeGuardFlow.ts, 2, 14))
>a : Symbol(a, Decl(destructuringTypeGuardFlow.ts, 28, 29))
>b : Symbol(b, Decl(destructuringTypeGuardFlow.ts, 4, 14))
>text : Symbol(text, Decl(destructuringTypeGuardFlow.ts, 28, 31))
>bBar.elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bBar : Symbol(bBar, Decl(destructuringTypeGuardFlow.ts, 25, 5))
>elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
const right: number = bBar.elem2.bar;
>right : Symbol(right, Decl(destructuringTypeGuardFlow.ts, 29, 7))
>bBar.elem2.bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
>bBar.elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bBar : Symbol(bBar, Decl(destructuringTypeGuardFlow.ts, 25, 5))
>elem2 : Symbol(elem2, Decl(destructuringTypeGuardFlow.ts, 25, 24))
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 0, 12))
const wrong: number = bar;
>wrong : Symbol(wrong, Decl(destructuringTypeGuardFlow.ts, 30, 7))
>bar : Symbol(bar, Decl(destructuringTypeGuardFlow.ts, 28, 9))
const another: string = baz;
>another : Symbol(another, Decl(destructuringTypeGuardFlow.ts, 31, 7))
>baz : Symbol(baz, Decl(destructuringTypeGuardFlow.ts, 28, 14))
const aAgain: number = a;
>aAgain : Symbol(aAgain, Decl(destructuringTypeGuardFlow.ts, 32, 7))
>a : Symbol(a, Decl(destructuringTypeGuardFlow.ts, 28, 29))
const bAgain: string = text;
>bAgain : Symbol(bAgain, Decl(destructuringTypeGuardFlow.ts, 33, 7))
>text : Symbol(text, Decl(destructuringTypeGuardFlow.ts, 28, 31))
}
@@ -0,0 +1,158 @@
=== tests/cases/compiler/destructuringTypeGuardFlow.ts ===
type foo = {
>foo : foo
bar: number | null;
>bar : number | null
>null : null
baz: string;
>baz : string
nested: {
>nested : { a: number; b: string | null; }
a: number;
>a : number
b: string | null;
>b : string | null
>null : null
}
};
const aFoo: foo = { bar: 3, baz: "b", nested: { a: 1, b: "y" } };
>aFoo : foo
>foo : foo
>{ bar: 3, baz: "b", nested: { a: 1, b: "y" } } : { bar: number; baz: string; nested: { a: number; b: string; }; }
>bar : number
>3 : 3
>baz : string
>"b" : "b"
>nested : { a: number; b: string; }
>{ a: 1, b: "y" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"y" : "y"
if (aFoo.bar && aFoo.nested.b) {
>aFoo.bar && aFoo.nested.b : string | 0 | null
>aFoo.bar : number | null
>aFoo : foo
>bar : number | null
>aFoo.nested.b : string | null
>aFoo.nested : { a: number; b: string | null; }
>aFoo : foo
>nested : { a: number; b: string | null; }
>b : string | null
const { bar, baz, nested: {a, b: text} } = aFoo;
>bar : number
>baz : string
>nested : any
>a : number
>b : any
>text : string
>aFoo : foo
const right: number = aFoo.bar;
>right : number
>aFoo.bar : number
>aFoo : foo
>bar : number
const wrong: number = bar;
>wrong : number
>bar : number
const another: string = baz;
>another : string
>baz : string
const aAgain: number = a;
>aAgain : number
>a : number
const bAgain: string = text;
>bAgain : string
>text : string
}
type bar = {
>bar : bar
elem1: number | null;
>elem1 : number | null
>null : null
elem2: foo | null;
>elem2 : foo | null
>foo : foo
>null : null
};
const bBar = { elem1: 7, elem2: aFoo };
>bBar : { elem1: number; elem2: foo; }
>{ elem1: 7, elem2: aFoo } : { elem1: number; elem2: foo; }
>elem1 : number
>7 : 7
>elem2 : foo
>aFoo : foo
if (bBar.elem2 && bBar.elem2.bar && bBar.elem2.nested.b) {
>bBar.elem2 && bBar.elem2.bar && bBar.elem2.nested.b : string | 0 | null
>bBar.elem2 && bBar.elem2.bar : number | null
>bBar.elem2 : foo
>bBar : { elem1: number; elem2: foo; }
>elem2 : foo
>bBar.elem2.bar : number | null
>bBar.elem2 : foo
>bBar : { elem1: number; elem2: foo; }
>elem2 : foo
>bar : number | null
>bBar.elem2.nested.b : string | null
>bBar.elem2.nested : { a: number; b: string | null; }
>bBar.elem2 : foo
>bBar : { elem1: number; elem2: foo; }
>elem2 : foo
>nested : { a: number; b: string | null; }
>b : string | null
const { bar, baz, nested: {a, b: text} } = bBar.elem2;
>bar : number
>baz : string
>nested : any
>a : number
>b : any
>text : string
>bBar.elem2 : foo
>bBar : { elem1: number; elem2: foo; }
>elem2 : foo
const right: number = bBar.elem2.bar;
>right : number
>bBar.elem2.bar : number
>bBar.elem2 : foo
>bBar : { elem1: number; elem2: foo; }
>elem2 : foo
>bar : number
const wrong: number = bar;
>wrong : number
>bar : number
const another: string = baz;
>another : string
>baz : string
const aAgain: number = a;
>aAgain : number
>a : number
const bAgain: string = text;
>bAgain : string
>text : string
}
@@ -0,0 +1,13 @@
/a.js(4,9): error TS2322: Type '0' is not assignable to type '() => void'.
==== /a.js (1 errors) ====
const o = {
a() {
// Should not be treated as a declaration. Should be an error.
this.a = 0;
~~~~~~
!!! error TS2322: Type '0' is not assignable to type '() => void'.
}
};
@@ -0,0 +1,16 @@
/a.js(4,9): error TS2322: Type '0' is not assignable to type '() => void'.
==== /a.js (1 errors) ====
const o = {
a() {
// Should not be treated as a declaration. Should be an error.
this.a = 0;
~~~~~~
!!! error TS2322: Type '0' is not assignable to type '() => void'.
},
b() {
this.b = () => {}; // OK
}
};
@@ -0,0 +1,15 @@
=== /a.js ===
const o = {
>o : Symbol(o, Decl(a.js, 0, 5))
a() {
>a : Symbol(a, Decl(a.js, 0, 11))
// Should not be treated as a declaration.
this.a = () => {};
>this.a : Symbol(a, Decl(a.js, 0, 11))
>this : Symbol(o, Decl(a.js, 0, 9))
>a : Symbol(a, Decl(a.js, 0, 11))
}
};
@@ -0,0 +1,18 @@
=== /a.js ===
const o = {
>o : { [x: string]: any; a(): void; }
>{ a() { // Should not be treated as a declaration. this.a = () => {}; }} : { [x: string]: any; a(): void; }
a() {
>a : () => void
// Should not be treated as a declaration.
this.a = () => {};
>this.a = () => {} : () => void
>this.a : () => void
>this : { [x: string]: any; a(): void; }
>a : () => void
>() => {} : () => void
}
};
@@ -0,0 +1,13 @@
=== tests/cases/conformance/jsdoc/indices.js ===
/** @type {Object.<string, number>} */
var o1;
>o1 : Symbol(o1, Decl(indices.js, 1, 3))
/** @type {Object.<number, boolean>} */
var o2;
>o2 : Symbol(o2, Decl(indices.js, 3, 3))
/** @type {Object.<boolean, string>} */
var o3;
>o3 : Symbol(o3, Decl(indices.js, 5, 3))
@@ -0,0 +1,13 @@
=== tests/cases/conformance/jsdoc/indices.js ===
/** @type {Object.<string, number>} */
var o1;
>o1 : { [x: string]: number; }
/** @type {Object.<number, boolean>} */
var o2;
>o2 : { [x: number]: boolean; }
/** @type {Object.<boolean, string>} */
var o3;
>o3 : any
@@ -0,0 +1,129 @@
tests/cases/conformance/jsdoc/b.js(4,13): error TS2352: Type 'number' cannot be converted to type 'string'.
tests/cases/conformance/jsdoc/b.js(45,16): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeBase'.
Property 'p' is missing in type 'SomeOther'.
tests/cases/conformance/jsdoc/b.js(49,19): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeDerived'.
Property 'x' is missing in type 'SomeOther'.
tests/cases/conformance/jsdoc/b.js(51,17): error TS2352: Type 'SomeDerived' cannot be converted to type 'SomeOther'.
Property 'q' is missing in type 'SomeDerived'.
tests/cases/conformance/jsdoc/b.js(52,17): error TS2352: Type 'SomeBase' cannot be converted to type 'SomeOther'.
Property 'q' is missing in type 'SomeBase'.
tests/cases/conformance/jsdoc/b.js(58,1): error TS2322: Type '{ p: string | number | undefined; }' is not assignable to type 'SomeBase'.
Types of property 'p' are incompatible.
Type 'string | number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.
tests/cases/conformance/jsdoc/b.js(66,8): error TS2352: Type 'boolean' cannot be converted to type 'string | number'.
tests/cases/conformance/jsdoc/b.js(66,15): error TS2304: Cannot find name 'numOrStr'.
tests/cases/conformance/jsdoc/b.js(66,24): error TS1005: '}' expected.
tests/cases/conformance/jsdoc/b.js(66,38): error TS2454: Variable 'numOrStr' is used before being assigned.
tests/cases/conformance/jsdoc/b.js(67,2): error TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsdoc/b.js(67,8): error TS2454: Variable 'numOrStr' is used before being assigned.
==== tests/cases/conformance/jsdoc/a.ts (0 errors) ====
var W: string;
==== tests/cases/conformance/jsdoc/b.js (12 errors) ====
// @ts-check
var W = /** @type {string} */(/** @type {*} */ (4));
var W = /** @type {string} */(4); // Error
~~~~~~~~~~~~~~
!!! error TS2352: Type 'number' cannot be converted to type 'string'.
/** @type {*} */
var a;
/** @type {string} */
var s;
var a = /** @type {*} */("" + 4);
var s = "" + /** @type {*} */(4);
class SomeBase {
constructor() {
this.p = 42;
}
}
class SomeDerived extends SomeBase {
constructor() {
super();
this.x = 42;
}
}
class SomeOther {
constructor() {
this.q = 42;
}
}
function SomeFakeClass() {
/** @type {string|number} */
this.p = "bar";
}
// Type assertion should check for assignability in either direction
var someBase = new SomeBase();
var someDerived = new SomeDerived();
var someOther = new SomeOther();
var someFakeClass = new SomeFakeClass();
someBase = /** @type {SomeBase} */(someDerived);
someBase = /** @type {SomeBase} */(someBase);
someBase = /** @type {SomeBase} */(someOther); // Error
~~~~~~~~~~~~~~~~
!!! error TS2352: Type 'SomeOther' cannot be converted to type 'SomeBase'.
!!! error TS2352: Property 'p' is missing in type 'SomeOther'.
someDerived = /** @type {SomeDerived} */(someDerived);
someDerived = /** @type {SomeDerived} */(someBase);
someDerived = /** @type {SomeDerived} */(someOther); // Error
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Type 'SomeOther' cannot be converted to type 'SomeDerived'.
!!! error TS2352: Property 'x' is missing in type 'SomeOther'.
someOther = /** @type {SomeOther} */(someDerived); // Error
~~~~~~~~~~~~~~~~~
!!! error TS2352: Type 'SomeDerived' cannot be converted to type 'SomeOther'.
!!! error TS2352: Property 'q' is missing in type 'SomeDerived'.
someOther = /** @type {SomeOther} */(someBase); // Error
~~~~~~~~~~~~~~~~~
!!! error TS2352: Type 'SomeBase' cannot be converted to type 'SomeOther'.
!!! error TS2352: Property 'q' is missing in type 'SomeBase'.
someOther = /** @type {SomeOther} */(someOther);
someFakeClass = someBase;
someFakeClass = someDerived;
someBase = someFakeClass; // Error
~~~~~~~~
!!! error TS2322: Type '{ p: string | number | undefined; }' is not assignable to type 'SomeBase'.
!!! error TS2322: Types of property 'p' are incompatible.
!!! error TS2322: Type 'string | number | undefined' is not assignable to type 'number'.
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
someBase = /** @type {SomeBase} */(someFakeClass);
// Type assertion cannot be a type-predicate type
/** @type {number | string} */
var numOrStr;
/** @type {string} */
var str;
if(/** @type {numOrStr is string} */(numOrStr === undefined)) { // Error
~~~~~~~~~~~~~~~
!!! error TS2352: Type 'boolean' cannot be converted to type 'string | number'.
~~~~~~~~
!!! error TS2304: Cannot find name 'numOrStr'.
~~
!!! error TS1005: '}' expected.
~~~~~~~~
!!! error TS2454: Variable 'numOrStr' is used before being assigned.
str = numOrStr; // Error, no narrowing occurred
~~~
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
~~~~~~~~
!!! error TS2454: Variable 'numOrStr' is used before being assigned.
}
@@ -0,0 +1,151 @@
//// [tests/cases/conformance/jsdoc/jsdocTypeTagCast.ts] ////
//// [a.ts]
var W: string;
//// [b.js]
// @ts-check
var W = /** @type {string} */(/** @type {*} */ (4));
var W = /** @type {string} */(4); // Error
/** @type {*} */
var a;
/** @type {string} */
var s;
var a = /** @type {*} */("" + 4);
var s = "" + /** @type {*} */(4);
class SomeBase {
constructor() {
this.p = 42;
}
}
class SomeDerived extends SomeBase {
constructor() {
super();
this.x = 42;
}
}
class SomeOther {
constructor() {
this.q = 42;
}
}
function SomeFakeClass() {
/** @type {string|number} */
this.p = "bar";
}
// Type assertion should check for assignability in either direction
var someBase = new SomeBase();
var someDerived = new SomeDerived();
var someOther = new SomeOther();
var someFakeClass = new SomeFakeClass();
someBase = /** @type {SomeBase} */(someDerived);
someBase = /** @type {SomeBase} */(someBase);
someBase = /** @type {SomeBase} */(someOther); // Error
someDerived = /** @type {SomeDerived} */(someDerived);
someDerived = /** @type {SomeDerived} */(someBase);
someDerived = /** @type {SomeDerived} */(someOther); // Error
someOther = /** @type {SomeOther} */(someDerived); // Error
someOther = /** @type {SomeOther} */(someBase); // Error
someOther = /** @type {SomeOther} */(someOther);
someFakeClass = someBase;
someFakeClass = someDerived;
someBase = someFakeClass; // Error
someBase = /** @type {SomeBase} */(someFakeClass);
// Type assertion cannot be a type-predicate type
/** @type {number | string} */
var numOrStr;
/** @type {string} */
var str;
if(/** @type {numOrStr is string} */(numOrStr === undefined)) { // Error
str = numOrStr; // Error, no narrowing occurred
}
//// [a.js]
var W;
//// [b.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
// @ts-check
var W = ((4));
var W = (4); // Error
/** @type {*} */
var a;
/** @type {string} */
var s;
var a = ("" + 4);
var s = "" + (4);
var SomeBase = (function () {
function SomeBase() {
this.p = 42;
}
return SomeBase;
}());
var SomeDerived = (function (_super) {
__extends(SomeDerived, _super);
function SomeDerived() {
var _this = _super.call(this) || this;
_this.x = 42;
return _this;
}
return SomeDerived;
}(SomeBase));
var SomeOther = (function () {
function SomeOther() {
this.q = 42;
}
return SomeOther;
}());
function SomeFakeClass() {
/** @type {string|number} */
this.p = "bar";
}
// Type assertion should check for assignability in either direction
var someBase = new SomeBase();
var someDerived = new SomeDerived();
var someOther = new SomeOther();
var someFakeClass = new SomeFakeClass();
someBase = (someDerived);
someBase = (someBase);
someBase = (someOther); // Error
someDerived = (someDerived);
someDerived = (someBase);
someDerived = (someOther); // Error
someOther = (someDerived); // Error
someOther = (someBase); // Error
someOther = (someOther);
someFakeClass = someBase;
someFakeClass = someDerived;
someBase = someFakeClass; // Error
someBase = (someFakeClass);
// Type assertion cannot be a type-predicate type
/** @type {number | string} */
var numOrStr;
/** @type {string} */
var str;
if ((numOrStr === undefined)) {
str = numOrStr; // Error, no narrowing occurred
}
@@ -1,4 +1,4 @@
tests/cases/compiler/keyofIsLiteralContexualType.ts(5,9): error TS2322: Type '("a" | "b" | "c")[]' is not assignable to type 'keyof T[]'.
tests/cases/compiler/keyofIsLiteralContexualType.ts(5,9): error TS2322: Type '("a" | "b" | "c")[]' is not assignable to type '(keyof T)[]'.
Type '"a" | "b" | "c"' is not assignable to type 'keyof T'.
Type '"c"' is not assignable to type 'keyof T'.
Type '"c"' is not assignable to type '"a" | "b"'.
@@ -12,7 +12,7 @@ tests/cases/compiler/keyofIsLiteralContexualType.ts(13,11): error TS2339: Proper
let a: (keyof T)[] = ["a", "b"];
let b: (keyof T)[] = ["a", "b", "c"];
~
!!! error TS2322: Type '("a" | "b" | "c")[]' is not assignable to type 'keyof T[]'.
!!! error TS2322: Type '("a" | "b" | "c")[]' is not assignable to type '(keyof T)[]'.
!!! error TS2322: Type '"a" | "b" | "c"' is not assignable to type 'keyof T'.
!!! error TS2322: Type '"c"' is not assignable to type 'keyof T'.
!!! error TS2322: Type '"c"' is not assignable to type '"a" | "b"'.
@@ -66,45 +66,47 @@ class Y {
>Y : Symbol(Y, Decl(input.js, 19, 10))
mistake() {
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
}
m() {
>m : Symbol(Y.m, Decl(input.js, 22, 5), Decl(input.js, 25, 19))
>m : Symbol(Y.m, Decl(input.js, 22, 5))
}
constructor() {
this.m = this.m.bind(this);
>this.m : Symbol(Y.m, Decl(input.js, 22, 5), Decl(input.js, 25, 19))
>this.m : Symbol(Y.m, Decl(input.js, 22, 5))
>this : Symbol(Y, Decl(input.js, 19, 10))
>m : Symbol(Y.m, Decl(input.js, 22, 5), Decl(input.js, 25, 19))
>this.m : Symbol(Y.m, Decl(input.js, 22, 5), Decl(input.js, 25, 19))
>m : Symbol(Y.m, Decl(input.js, 22, 5))
>this.m.bind : Symbol(Function.bind, Decl(lib.d.ts, --, --))
>this.m : Symbol(Y.m, Decl(input.js, 22, 5))
>this : Symbol(Y, Decl(input.js, 19, 10))
>m : Symbol(Y.m, Decl(input.js, 22, 5), Decl(input.js, 25, 19))
>m : Symbol(Y.m, Decl(input.js, 22, 5))
>bind : Symbol(Function.bind, Decl(lib.d.ts, --, --))
>this : Symbol(Y, Decl(input.js, 19, 10))
this.mistake = 'even more nonsense';
>this.mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>this.mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
>this : Symbol(Y, Decl(input.js, 19, 10))
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
}
}
Y.prototype.mistake = true;
>Y.prototype.mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>Y.prototype : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>Y.prototype.mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
>Y.prototype : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
>Y : Symbol(Y, Decl(input.js, 19, 10))
>prototype : Symbol(Y.prototype)
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
let y = new Y();
>y : Symbol(y, Decl(input.js, 31, 3))
>Y : Symbol(Y, Decl(input.js, 19, 10))
y.m();
>y.m : Symbol(Y.m, Decl(input.js, 22, 5), Decl(input.js, 25, 19))
>y.m : Symbol(Y.m, Decl(input.js, 22, 5))
>y : Symbol(y, Decl(input.js, 31, 3))
>m : Symbol(Y.m, Decl(input.js, 22, 5), Decl(input.js, 25, 19))
>m : Symbol(Y.m, Decl(input.js, 22, 5))
y.mistake();
>y.mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>y.mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
>y : Symbol(y, Decl(input.js, 31, 3))
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 26, 35), Decl(input.js, 29, 1))
>mistake : Symbol(Y.mistake, Decl(input.js, 20, 9), Decl(input.js, 29, 1))
@@ -87,20 +87,20 @@ class Y {
>mistake : any
}
m() {
>m : any
>m : () => void
}
constructor() {
this.m = this.m.bind(this);
>this.m = this.m.bind(this) : any
>this.m : any
>this.m : () => void
>this : this
>m : any
>m : () => void
>this.m.bind(this) : any
>this.m.bind : any
>this.m : any
>this.m.bind : (this: Function, thisArg: any, ...argArray: any[]) => any
>this.m : () => void
>this : this
>m : any
>bind : any
>m : () => void
>bind : (this: Function, thisArg: any, ...argArray: any[]) => any
>this : this
this.mistake = 'even more nonsense';
@@ -126,10 +126,10 @@ let y = new Y();
>Y : typeof Y
y.m();
>y.m() : any
>y.m : any
>y.m() : void
>y.m : () => void
>y : Y
>m : any
>m : () => void
y.mistake();
>y.mistake() : any
@@ -62,9 +62,21 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(123,20
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(128,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(132,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(152,68): error TS2344: Type 'T | "d"' does not satisfy the constraint 'Keys'.
Type '"d"' is not assignable to type 'Keys'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(159,31): error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
Types of property ''a'' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(162,31): error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(163,35): error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(164,51): error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(165,51): error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(166,45): error TS2677: A type predicate's type must be assignable to its parameter's type.
Type 'NeedsFoo<number>' is not assignable to type 'number'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(166,54): error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (54 errors) ====
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (62 errors) ====
class A {
~
!!! error TS2300: Duplicate identifier 'A'.
@@ -175,7 +187,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39
// No type guard in if statement
if (hasNoTypeGuard(a)) {
a.propB;
a.propB;
~~~~~
!!! error TS2551: Property 'propB' does not exist on type 'A'. Did you mean 'propA'?
}
@@ -208,7 +220,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39
return true;
};
// No matching signature
// No matching signature
var assign3: (p1, p2) => p1 is A;
assign3 = function(p1, p2, p3): p1 is A {
~~~~~~~
@@ -326,4 +338,47 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(136,39
var x: A;
if (hasMissingParameter()) {
x.propA;
}
}
// repro #17297
type Keys = 'a'|'b'|'c'
type KeySet<T extends Keys> = { [k in T]: true }
// expected an error, since Keys doesn't have a 'd'
declare function hasKey<T extends Keys>(x: KeySet<T>): x is KeySet<T|'d'>;
~~~~~
!!! error TS2344: Type 'T | "d"' does not satisfy the constraint 'Keys'.
!!! error TS2344: Type '"d"' is not assignable to type 'Keys'.
type Foo = { 'a': string; }
type Bar = { 'a': number; }
interface NeedsFoo<T extends Foo> {
foo: T;
isFoo(): this is NeedsFoo<Bar>; // should error
~~~
!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
!!! error TS2344: Types of property ''a'' are incompatible.
!!! error TS2344: Type 'number' is not assignable to type 'string'.
};
declare var anError: NeedsFoo<Bar>; // error, as expected
~~~
!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
declare var alsoAnError: NeedsFoo<number>; // also error, as expected
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
declare function newError1(x: any): x is NeedsFoo<Bar>; // should error
~~~
!!! error TS2344: Type 'Bar' does not satisfy the constraint 'Foo'.
declare function newError2(x: any): x is NeedsFoo<number>; // should error
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
declare function newError3(x: number): x is NeedsFoo<number>; // should error
~~~~~~~~~~~~~~~~
!!! error TS2677: A type predicate's type must be assignable to its parameter's type.
!!! error TS2677: Type 'NeedsFoo<number>' is not assignable to type 'number'.
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'Foo'.
@@ -67,7 +67,7 @@ if (funA(0, a)) {
// No type guard in if statement
if (hasNoTypeGuard(a)) {
a.propB;
a.propB;
}
// Type predicate type is not assignable
@@ -86,7 +86,7 @@ assign2 = function(p1, p2): p2 is A {
return true;
};
// No matching signature
// No matching signature
var assign3: (p1, p2) => p1 is A;
assign3 = function(p1, p2, p3): p1 is A {
return true;
@@ -142,7 +142,30 @@ function b7({a, b, c: {p1}}, p2, p3): p1 is A {
var x: A;
if (hasMissingParameter()) {
x.propA;
}
}
// repro #17297
type Keys = 'a'|'b'|'c'
type KeySet<T extends Keys> = { [k in T]: true }
// expected an error, since Keys doesn't have a 'd'
declare function hasKey<T extends Keys>(x: KeySet<T>): x is KeySet<T|'d'>;
type Foo = { 'a': string; }
type Bar = { 'a': number; }
interface NeedsFoo<T extends Foo> {
foo: T;
isFoo(): this is NeedsFoo<Bar>; // should error
};
declare var anError: NeedsFoo<Bar>; // error, as expected
declare var alsoAnError: NeedsFoo<number>; // also error, as expected
declare function newError1(x: any): x is NeedsFoo<Bar>; // should error
declare function newError2(x: any): x is NeedsFoo<number>; // should error
declare function newError3(x: number): x is NeedsFoo<number>; // should error
//// [typeGuardFunctionErrors.js]
var __extends = (this && this.__extends) || (function () {
@@ -224,7 +247,7 @@ var assign2;
assign2 = function (p1, p2) {
return true;
};
// No matching signature
// No matching signature
var assign3;
assign3 = function (p1, p2, p3) {
return true;
@@ -290,3 +313,4 @@ var x;
if (hasMissingParameter()) {
x.propA;
}
;
@@ -0,0 +1,36 @@
// @strictNullChecks: true
type foo = {
bar: number | null;
baz: string;
nested: {
a: number;
b: string | null;
}
};
const aFoo: foo = { bar: 3, baz: "b", nested: { a: 1, b: "y" } };
if (aFoo.bar && aFoo.nested.b) {
const { bar, baz, nested: {a, b: text} } = aFoo;
const right: number = aFoo.bar;
const wrong: number = bar;
const another: string = baz;
const aAgain: number = a;
const bAgain: string = text;
}
type bar = {
elem1: number | null;
elem2: foo | null;
};
const bBar = { elem1: 7, elem2: aFoo };
if (bBar.elem2 && bBar.elem2.bar && bBar.elem2.nested.b) {
const { bar, baz, nested: {a, b: text} } = bBar.elem2;
const right: number = bBar.elem2.bar;
const wrong: number = bar;
const another: string = baz;
const aAgain: number = a;
const bAgain: string = text;
}
@@ -0,0 +1,12 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @noImplicitThis: true
// @Filename: /a.js
const o = {
a() {
// Should not be treated as a declaration. Should be an error.
this.a = 0;
}
};
@@ -0,0 +1,12 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @noImplicitThis: true
// @Filename: /a.js
const o = {
a() {
// Should not be treated as a declaration.
this.a = () => {};
}
};
@@ -67,7 +67,7 @@ if (funA(0, a)) {
// No type guard in if statement
if (hasNoTypeGuard(a)) {
a.propB;
a.propB;
}
// Type predicate type is not assignable
@@ -86,7 +86,7 @@ assign2 = function(p1, p2): p2 is A {
return true;
};
// No matching signature
// No matching signature
var assign3: (p1, p2) => p1 is A;
assign3 = function(p1, p2, p3): p1 is A {
return true;
@@ -142,4 +142,26 @@ function b7({a, b, c: {p1}}, p2, p3): p1 is A {
var x: A;
if (hasMissingParameter()) {
x.propA;
}
}
// repro #17297
type Keys = 'a'|'b'|'c'
type KeySet<T extends Keys> = { [k in T]: true }
// expected an error, since Keys doesn't have a 'd'
declare function hasKey<T extends Keys>(x: KeySet<T>): x is KeySet<T|'d'>;
type Foo = { 'a': string; }
type Bar = { 'a': number; }
interface NeedsFoo<T extends Foo> {
foo: T;
isFoo(): this is NeedsFoo<Bar>; // should error
};
declare var anError: NeedsFoo<Bar>; // error, as expected
declare var alsoAnError: NeedsFoo<number>; // also error, as expected
declare function newError1(x: any): x is NeedsFoo<Bar>; // should error
declare function newError2(x: any): x is NeedsFoo<number>; // should error
declare function newError3(x: number): x is NeedsFoo<number>; // should error
@@ -0,0 +1,10 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @Filename: indices.js
/** @type {Object.<string, number>} */
var o1;
/** @type {Object.<number, boolean>} */
var o2;
/** @type {Object.<boolean, string>} */
var o3;
@@ -0,0 +1,78 @@
// @allowJS: true
// @suppressOutputPathCheck: true
// @strictNullChecks: true
// @filename: a.ts
var W: string;
// @filename: b.js
// @ts-check
var W = /** @type {string} */(/** @type {*} */ (4));
var W = /** @type {string} */(4); // Error
/** @type {*} */
var a;
/** @type {string} */
var s;
var a = /** @type {*} */("" + 4);
var s = "" + /** @type {*} */(4);
class SomeBase {
constructor() {
this.p = 42;
}
}
class SomeDerived extends SomeBase {
constructor() {
super();
this.x = 42;
}
}
class SomeOther {
constructor() {
this.q = 42;
}
}
function SomeFakeClass() {
/** @type {string|number} */
this.p = "bar";
}
// Type assertion should check for assignability in either direction
var someBase = new SomeBase();
var someDerived = new SomeDerived();
var someOther = new SomeOther();
var someFakeClass = new SomeFakeClass();
someBase = /** @type {SomeBase} */(someDerived);
someBase = /** @type {SomeBase} */(someBase);
someBase = /** @type {SomeBase} */(someOther); // Error
someDerived = /** @type {SomeDerived} */(someDerived);
someDerived = /** @type {SomeDerived} */(someBase);
someDerived = /** @type {SomeDerived} */(someOther); // Error
someOther = /** @type {SomeOther} */(someDerived); // Error
someOther = /** @type {SomeOther} */(someBase); // Error
someOther = /** @type {SomeOther} */(someOther);
someFakeClass = someBase;
someFakeClass = someDerived;
someBase = someFakeClass; // Error
someBase = /** @type {SomeBase} */(someFakeClass);
// Type assertion cannot be a type-predicate type
/** @type {number | string} */
var numOrStr;
/** @type {string} */
var str;
if(/** @type {numOrStr is string} */(numOrStr === undefined)) { // Error
str = numOrStr; // Error, no narrowing occurred
}
@@ -0,0 +1,13 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @Filename: context.js
const obj = {
prop: 2,
method() {
this;
this.prop;
this.method;
this.unknown; // ok, obj has a string indexer
}
}
@@ -0,0 +1,4 @@
/// <reference path='fourslash.ts' />
//// var x: [|?|] = 12;
verify.rangeAfterCodeFix("any");
@@ -0,0 +1,4 @@
/// <reference path='fourslash.ts' />
//// var x: [|*|] = 12;
verify.rangeAfterCodeFix("any");
@@ -0,0 +1,4 @@
/// <reference path='fourslash.ts' />
//// var x: [|......number[][]|] = 12;
verify.rangeAfterCodeFix("number[][][][]");
@@ -0,0 +1,4 @@
/// <reference path='fourslash.ts' />
//// var x: [|Array.<number>|] = 12;
verify.rangeAfterCodeFix("number[]");
@@ -0,0 +1,5 @@
// @strict: true
/// <reference path='fourslash.ts' />
//// var x: [|?number|] = 12;
verify.rangeAfterCodeFix("number | null", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0);
@@ -0,0 +1,5 @@
// @strict: true
/// <reference path='fourslash.ts' />
//// var x: [|number?|] = 12;
verify.rangeAfterCodeFix("number | null | undefined", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 1);
@@ -0,0 +1,4 @@
/// <reference path='fourslash.ts' />
//// var x: [|!number|] = 12;
verify.rangeAfterCodeFix("number");
@@ -0,0 +1,4 @@
/// <reference path='fourslash.ts' />
//// var x: [|function(this: number, number): string|] = 12;
verify.rangeAfterCodeFix("(this: number, arg1: number) => string");
@@ -0,0 +1,4 @@
/// <reference path='fourslash.ts' />
//// var x: [|function(new: number)|] = 12;
verify.rangeAfterCodeFix("new () => number");
@@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
// See also `jsPropertyAssignedAfterMethodDeclaration.ts`
// @noLib: true
// @allowJs: true
// @noImplicitThis: true
// @Filename: /a.js
////const o = {
//// test/*1*/() {
//// this./*2*/test = 0;
//// }
////};
verify.quickInfoAt("1", "(method) test(): void");
verify.quickInfoAt("2", "(method) test(): void");
@@ -0,0 +1,21 @@
/// <reference path='fourslash.ts'/>
// @Filename: keyof.ts
//// function doSomethingWithKeys<T>(...keys: (keyof T)[]) { }
////
//// const /*1*/utilityFunctions = {
//// doSomethingWithKeys
//// };
// @Filename: typeof.ts
//// class Foo { static a: number; }
//// function doSomethingWithTypes(...statics: (typeof Foo)[]) {}
////
//// const /*2*/utilityFunctions = {
//// doSomethingWithTypes
//// };
verify.quickInfos({
1: "const utilityFunctions: {\n doSomethingWithKeys: <T>(...keys: (keyof T)[]) => void;\n}",
2: "const utilityFunctions: {\n doSomethingWithTypes: (...statics: (typeof Foo)[]) => void;\n}"
});