Address PR comments

1. Add undefined only when an initialized parameter is required (not
optional).
2. Create isRequiredInitializedParameter helper function
3. Call this function only once from declarationEmitter
This commit is contained in:
Nathan Shively-Sanders 2017-02-01 09:41:44 -08:00
parent 7cf595a381
commit 6f7c984c42
3 changed files with 25 additions and 21 deletions

View File

@ -2695,7 +2695,7 @@ namespace ts {
writeSpace(writer);
let type = getTypeOfSymbol(p);
if (strictNullChecks && parameterNode.initializer && !(getModifierFlags(parameterNode) & ModifierFlags.ParameterPropertyModifier)) {
if (isRequiredInitializedParameter(parameterNode)) {
type = includeFalsyTypes(type, TypeFlags.Undefined);
}
buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack);
@ -3182,12 +3182,6 @@ namespace ts {
}
return parentType;
}
// In strict null checking mode, a default value of a binding pattern adds undefined,
// which should be removed to get the type of the elements
const func = getContainingFunction(declaration);
if (strictNullChecks && func && !func.body && getFalsyFlags(parentType) & TypeFlags.Undefined) {
parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined);
}
let type: Type;
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
@ -20554,6 +20548,13 @@ namespace ts {
return false;
}
function isRequiredInitializedParameter(parameter: ParameterDeclaration) {
return strictNullChecks &&
!isOptionalParameter(parameter) &&
parameter.initializer &&
!(getModifierFlags(parameter) & ModifierFlags.ParameterPropertyModifier);
}
function getNodeCheckFlags(node: Node): NodeCheckFlags {
node = getParseTreeNode(node);
return node ? getNodeLinks(node).flags : undefined;
@ -20648,13 +20649,9 @@ namespace ts {
let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
? getWidenedLiteralType(getTypeOfSymbol(symbol))
: unknownType;
if (strictNullChecks &&
declaration.kind === SyntaxKind.Parameter &&
(declaration as ParameterDeclaration).initializer &&
!(getModifierFlags(declaration) & ModifierFlags.ParameterPropertyModifier)) {
if (flags & TypeFormatFlags.AddUndefined) {
type = includeFalsyTypes(type, TypeFlags.Undefined);
}
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
}
@ -20753,6 +20750,7 @@ namespace ts {
isTopLevelValueImportEqualsWithEntityName,
isDeclarationVisible,
isImplementationOfOverload,
isRequiredInitializedParameter,
writeTypeOfDeclaration,
writeReturnTypeOfSignatureDeclaration,
writeTypeOfExpression,

View File

@ -322,13 +322,22 @@ namespace ts {
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
write(": ");
if (type) {
// use the checker's type, not the declared type,
// for non-optional initialized parameters that aren't a parameter property
const shouldUseResolverType = declaration.kind === SyntaxKind.Parameter &&
resolver.isRequiredInitializedParameter(declaration as ParameterDeclaration);
if (type && !shouldUseResolverType) {
// Write the type
emitType(type);
}
else {
errorNameNode = declaration.name;
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
let format = TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue;
if (shouldUseResolverType) {
format |= TypeFormatFlags.AddUndefined;
}
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, format, writer);
errorNameNode = undefined;
}
}
@ -1594,12 +1603,7 @@ namespace ts {
emitTypeOfVariableDeclarationFromTypeLiteral(node);
}
else if (!hasModifier(node.parent, ModifierFlags.Private)) {
// use the checker's type, not the declared type,
// for optional parameters and initialized ones that aren't a parameter property
const typeShouldAddUndefined = resolver.isOptionalParameter(node) ||
node.initializer && !(getModifierFlags(node) & ModifierFlags.ParameterPropertyModifier);
const typeNode = typeShouldAddUndefined ? undefined : node.type;
writeTypeOfDeclaration(node, typeNode, getParameterDeclarationTypeVisibilityError);
writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError);
}
function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {

View File

@ -2466,7 +2466,8 @@
InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type
InTypeAlias = 0x00000200, // Writing type in type alias declaration
UseTypeAliasValue = 0x00000400, // Serialize the type instead of using type-alias. This is needed when we emit declaration file.
SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type.
SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type.
AddUndefined = 0x00001000, // Add undefined to types of initialized, non-optional parameters
}
export const enum SymbolFormatFlags {
@ -2571,6 +2572,7 @@
isDeclarationVisible(node: Declaration): boolean;
collectLinkedAliases(node: Identifier): Node[];
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
isRequiredInitializedParameter(node: ParameterDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;