From ee0060bb2f6dce7bb43b15fc7e8a1d4e6d5b9074 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 23 Jan 2016 15:35:33 -0800 Subject: [PATCH] No readonly checks in type relationships + No assignments through namespace imports --- src/compiler/checker.ts | 69 +++++++++------------------- src/compiler/diagnosticMessages.json | 8 ---- 2 files changed, 22 insertions(+), 55 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e8a3cd115d0..7b0da6e4fcc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5641,13 +5641,6 @@ namespace ts { } return Ternary.False; } - if (isReadonlySymbol(sourceProp) && !isReadonlySymbol(targetProp)) { - if (reportErrors) { - reportError(Diagnostics.Property_0_is_read_only_in_type_1_but_writable_in_type_2, - symbolToString(targetProp), typeToString(source), typeToString(target)); - } - return Ternary.False; - } } } } @@ -5780,13 +5773,6 @@ namespace ts { } return Ternary.False; } - if (sourceInfo.isReadonly && !targetInfo.isReadonly) { - if (reportErrors) { - reportError(Diagnostics.Index_signature_is_read_only_in_type_0_but_writable_in_type_1, - typeToString(source), typeToString(target)); - } - return Ternary.False; - } return related; } return Ternary.True; @@ -5826,13 +5812,6 @@ namespace ts { } return Ternary.False; } - if ((sourceStringInfo && sourceStringInfo.isReadonly || sourceNumberInfo && sourceNumberInfo.isReadonly) && !targetInfo.isReadonly) { - if (reportErrors) { - reportError(Diagnostics.Index_signature_is_read_only_in_type_0_but_writable_in_type_1, - typeToString(source), typeToString(target)); - } - return Ternary.False; - } return related; } return Ternary.True; @@ -10401,36 +10380,19 @@ namespace ts { } function isReadonlySymbol(symbol: Symbol): boolean { - return symbol.flags & SymbolFlags.Property && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Readonly) !== 0; + return symbol.flags & SymbolFlags.Property && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Readonly) !== 0 || + symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor); } - function isReferenceToConstant(expr: Expression, symbol: Symbol): boolean { - if (symbol.flags & SymbolFlags.Variable) { - // A variable declared with 'const' is considered constant. - if (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Const) { - return true; - } - // An exported variable declared in an external module and accessed through a property - // or element access is considered constant. - if (expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) { - if (symbol.parent && symbol.parent.flags & SymbolFlags.ValueModule) { - const declaration = symbol.parent.valueDeclaration; - return declaration && (declaration.kind === SyntaxKind.SourceFile || - declaration.kind === SyntaxKind.ModuleDeclaration && (declaration).name.kind === SyntaxKind.StringLiteral); - } - } - } - if (symbol.flags & SymbolFlags.Accessor) { - // An get accessor with no corresponding set accessor is considered constant. - return !(symbol.flags & SymbolFlags.SetAccessor); - } - return false; + function isConstantSymbol(symbol: Symbol): boolean { + return symbol.flags & SymbolFlags.Variable && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0; } function isReferenceToReadonlyProperty(expr: Expression, symbol: Symbol): boolean { if (isReadonlySymbol(symbol)) { // Allow assignments to readonly properties within constructors of the same class declaration. - if ((expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) && + if (symbol.flags & SymbolFlags.Property && + (expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) && (expr as PropertyAccessExpression | ElementAccessExpression).expression.kind === SyntaxKind.ThisKeyword) { const func = getContainingFunction(expr); return !(func && func.kind === SyntaxKind.Constructor && func.parent === symbol.valueDeclaration.parent); @@ -10440,6 +10402,20 @@ namespace ts { return false; } + function isReferenceThroughNamespaceImport(expr: Expression): boolean { + if (expr.kind === SyntaxKind.PropertyAccessExpression || expr.kind === SyntaxKind.ElementAccessExpression) { + const node = skipParenthesizedNodes((expr as PropertyAccessExpression | ElementAccessExpression).expression); + if (node.kind === SyntaxKind.Identifier) { + const symbol = getNodeLinks(node).resolvedSymbol; + if (symbol.flags & SymbolFlags.Alias) { + const declaration = getDeclarationOfAliasSymbol(symbol); + return declaration && declaration.kind === SyntaxKind.NamespaceImport; + } + } + } + return false; + } + function checkReferenceExpression(expr: Expression, invalidReferenceMessage: DiagnosticMessage, constantVariableMessage: DiagnosticMessage): boolean { // References are combinations of identifiers, parentheses, and property accesses. const node = skipParenthesizedNodes(expr); @@ -10454,12 +10430,11 @@ namespace ts { const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol); if (symbol) { if (symbol !== unknownSymbol && symbol !== argumentsSymbol) { - if (symbol === undefinedSymbol || - !(symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Method | SymbolFlags.Accessor))) { + if (node.kind === SyntaxKind.Identifier && !(symbol.flags & SymbolFlags.Variable) || symbol.flags & SymbolFlags.EnumMember) { error(expr, invalidReferenceMessage); return false; } - if (isReferenceToConstant(node, symbol) || isReferenceToReadonlyProperty(node, symbol)) { + if (isConstantSymbol(symbol) || isReferenceToReadonlyProperty(node, symbol) || isReferenceThroughNamespaceImport(node)) { error(expr, constantVariableMessage); return false; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cb01650d13f..87de69bb4d5 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -995,10 +995,6 @@ "category": "Error", "code": 2342 }, - "Property '{0}' is read-only in type '{1}' but writable in type '{2}'.": { - "category": "Error", - "code": 2343 - }, "Type '{0}' does not satisfy the constraint '{1}'.": { "category": "Error", "code": 2344 @@ -1087,10 +1083,6 @@ "category": "Error", "code": 2365 }, - "Index signature is read-only in type '{0}' but writable in type '{1}'.": { - "category": "Error", - "code": 2366 - }, "Type parameter name cannot be '{0}'": { "category": "Error", "code": 2368