Make NodeArray readonly (#17213)

* Make NodeArray readonly

* Fix bug: use emptyArray instead of undefined

* Fix bug: Don't expose MutableNodeArray

* Undo trailing whitespace changes
This commit is contained in:
Andy 2017-07-18 10:38:21 -07:00 committed by GitHub
parent 80b19a09a1
commit 194c2bc2ca
23 changed files with 446 additions and 204 deletions

View File

@ -1327,7 +1327,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);
}
}

View File

@ -2670,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);
@ -2907,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[];
@ -3667,7 +3667,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));
@ -3675,7 +3675,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);
@ -3685,7 +3685,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;
@ -4738,7 +4738,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) {
@ -4825,14 +4825,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);
@ -14906,7 +14906,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) {
@ -14916,7 +14916,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
@ -15027,7 +15027,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
@ -15115,7 +15115,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;
@ -15179,7 +15179,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);
}
@ -15247,16 +15253,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
@ -15265,13 +15271,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;
}
@ -15288,7 +15292,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:
@ -15520,7 +15524,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)) {
@ -15552,7 +15556,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;
@ -17065,7 +17069,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) {
@ -18509,7 +18513,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;
@ -20955,7 +20959,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++) {

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);

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)) {

File diff suppressed because it is too large Load Diff

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();
}
@ -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

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;

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]);
}
/**

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) {

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]);

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;

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;
}

View File

@ -523,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;
}

View File

@ -2731,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;
}
@ -4739,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");
}

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);
}

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);
}
}

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,

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) &&

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:

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:

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];

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;
}

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;
}