mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into checkJSFiles
This commit is contained in:
@@ -2332,6 +2332,7 @@ namespace ts {
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression) {
|
||||
Debug.assert(isInJavaScriptFile(node));
|
||||
const container = getThisContainer(node, /*includeArrowFunctions*/false);
|
||||
switch (container.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
@@ -2342,6 +2343,7 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
|
||||
+28
-12
@@ -3973,7 +3973,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.TypeVariable) {
|
||||
const constraint = getBaseConstraintOfType(<TypeVariable>type);
|
||||
const constraint = getBaseConstraintOfType(type);
|
||||
return constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint);
|
||||
}
|
||||
return false;
|
||||
@@ -4989,16 +4989,32 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
|
||||
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) : getBaseConstraintOfType(type);
|
||||
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) :
|
||||
type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(<IndexedAccessType>type) :
|
||||
getBaseConstraintOfType(type);
|
||||
}
|
||||
|
||||
function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type {
|
||||
return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined;
|
||||
}
|
||||
|
||||
function getBaseConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
|
||||
const constraint = getResolvedBaseConstraint(type);
|
||||
return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined;
|
||||
function getConstraintOfIndexedAccess(type: IndexedAccessType) {
|
||||
const baseObjectType = getBaseConstraintOfType(type.objectType);
|
||||
const baseIndexType = getBaseConstraintOfType(type.indexType);
|
||||
return baseObjectType || baseIndexType ? getIndexedAccessType(baseObjectType || type.objectType, baseIndexType || type.indexType) : undefined;
|
||||
}
|
||||
|
||||
function getBaseConstraintOfType(type: Type): Type {
|
||||
if (type.flags & (TypeFlags.TypeVariable | TypeFlags.UnionOrIntersection)) {
|
||||
const constraint = getResolvedBaseConstraint(<TypeVariable | UnionOrIntersectionType>type);
|
||||
if (constraint !== noConstraintType && constraint !== circularConstraintType) {
|
||||
return constraint;
|
||||
}
|
||||
}
|
||||
else if (type.flags & TypeFlags.Index) {
|
||||
return stringType;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function hasNonCircularBaseConstraint(type: TypeVariable): boolean {
|
||||
@@ -5096,7 +5112,7 @@ namespace ts {
|
||||
* type itself. Note that the apparent type of a union type is the union type itself.
|
||||
*/
|
||||
function getApparentType(type: Type): Type {
|
||||
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(<TypeVariable>type) || emptyObjectType : type;
|
||||
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(type) || emptyObjectType : type;
|
||||
return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
|
||||
t.flags & TypeFlags.StringLike ? globalStringType :
|
||||
t.flags & TypeFlags.NumberLike ? globalNumberType :
|
||||
@@ -7921,7 +7937,7 @@ namespace ts {
|
||||
}
|
||||
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
|
||||
// A is the apparent type of S.
|
||||
const constraint = getBaseConstraintOfType(<IndexedAccessType>target);
|
||||
const constraint = getBaseConstraintOfType(target);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, constraint, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
@@ -7961,7 +7977,7 @@ namespace ts {
|
||||
else if (source.flags & TypeFlags.IndexedAccess) {
|
||||
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
|
||||
// A is the apparent type of S.
|
||||
const constraint = getBaseConstraintOfType(<IndexedAccessType>source);
|
||||
const constraint = getConstraintOfType(<IndexedAccessType>source);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(constraint, target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
@@ -9874,7 +9890,7 @@ namespace ts {
|
||||
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
|
||||
}
|
||||
if (flags & TypeFlags.TypeVariable) {
|
||||
return getTypeFacts(getBaseConstraintOfType(<TypeVariable>type) || emptyObjectType);
|
||||
return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType);
|
||||
}
|
||||
if (flags & TypeFlags.UnionOrIntersection) {
|
||||
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
|
||||
@@ -10686,7 +10702,7 @@ namespace ts {
|
||||
return targetType;
|
||||
}
|
||||
if (type.flags & TypeFlags.TypeVariable) {
|
||||
const constraint = getBaseConstraintOfType(<TypeVariable>type) || anyType;
|
||||
const constraint = getBaseConstraintOfType(type) || anyType;
|
||||
if (isTypeSubtypeOf(targetType, constraint)) {
|
||||
return getIntersectionType([type, targetType]);
|
||||
}
|
||||
@@ -16234,7 +16250,7 @@ namespace ts {
|
||||
function isLiteralContextualType(contextualType: Type) {
|
||||
if (contextualType) {
|
||||
if (contextualType.flags & TypeFlags.TypeVariable) {
|
||||
const constraint = getBaseConstraintOfType(<TypeVariable>contextualType) || emptyObjectType;
|
||||
const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType;
|
||||
// If the type parameter is constrained to the base primitive type we're checking for,
|
||||
// consider this a literal context. For example, given a type parameter 'T extends string',
|
||||
// this causes us to infer string literal types for T.
|
||||
@@ -17124,7 +17140,7 @@ namespace ts {
|
||||
// Check if we're indexing with a numeric type and the object type is a generic
|
||||
// type with a constraint that has a numeric index signature.
|
||||
if (maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && isTypeOfKind(indexType, TypeFlags.NumberLike)) {
|
||||
const constraint = getBaseConstraintOfType(<TypeVariable | UnionOrIntersectionType>objectType);
|
||||
const constraint = getBaseConstraintOfType(objectType);
|
||||
if (constraint && getIndexInfoOfType(constraint, IndexKind.Number)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
+31
-2
@@ -199,6 +199,8 @@ namespace ts {
|
||||
onEmitHelpers,
|
||||
onSetSourceFile,
|
||||
substituteNode,
|
||||
onBeforeEmitNodeArray,
|
||||
onAfterEmitNodeArray
|
||||
} = handlers;
|
||||
|
||||
const newLine = getNewLineCharacter(printerOptions);
|
||||
@@ -631,6 +633,11 @@ namespace ts {
|
||||
if (isExpression(node)) {
|
||||
return pipelineEmitExpression(trySubstituteNode(EmitHint.Expression, node));
|
||||
}
|
||||
|
||||
if (isToken(node)) {
|
||||
writeTokenText(kind);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function pipelineEmitExpression(node: Node): void {
|
||||
@@ -1553,6 +1560,10 @@ namespace ts {
|
||||
emitSignatureAndBody(node, emitSignatureHead);
|
||||
}
|
||||
|
||||
function emitBlockCallback(_hint: EmitHint, body: Node): void {
|
||||
emitBlockFunctionBody(<Block>body);
|
||||
}
|
||||
|
||||
function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) {
|
||||
const body = node.body;
|
||||
if (body) {
|
||||
@@ -1564,12 +1575,22 @@ namespace ts {
|
||||
|
||||
if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) {
|
||||
emitSignatureHead(node);
|
||||
emitBlockFunctionBody(body);
|
||||
if (onEmitNode) {
|
||||
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
|
||||
}
|
||||
else {
|
||||
emitBlockFunctionBody(body);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pushNameGenerationScope();
|
||||
emitSignatureHead(node);
|
||||
emitBlockFunctionBody(body);
|
||||
if (onEmitNode) {
|
||||
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
|
||||
}
|
||||
else {
|
||||
emitBlockFunctionBody(body);
|
||||
}
|
||||
popNameGenerationScope();
|
||||
}
|
||||
|
||||
@@ -2200,6 +2221,10 @@ namespace ts {
|
||||
write(getOpeningBracket(format));
|
||||
}
|
||||
|
||||
if (onBeforeEmitNodeArray) {
|
||||
onBeforeEmitNodeArray(children);
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
// Write a line terminator if the parent node was multi-line
|
||||
if (format & ListFormat.MultiLine) {
|
||||
@@ -2315,6 +2340,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (onAfterEmitNodeArray) {
|
||||
onAfterEmitNodeArray(children);
|
||||
}
|
||||
|
||||
if (format & ListFormat.BracketsMask) {
|
||||
write(getClosingBracket(format));
|
||||
}
|
||||
|
||||
@@ -1099,6 +1099,10 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode {
|
||||
return <KeywordTypeNode>createSynthesizedNode(kind);
|
||||
}
|
||||
|
||||
export function createFunctionDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
|
||||
const node = <FunctionDeclaration>createSynthesizedNode(SyntaxKind.FunctionDeclaration);
|
||||
node.decorators = asNodeArray(decorators);
|
||||
|
||||
@@ -333,7 +333,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getLineStarts(sourceFile: SourceFile): number[] {
|
||||
export function getLineStarts(sourceFile: SourceFileLike): number[] {
|
||||
return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
|
||||
}
|
||||
|
||||
|
||||
@@ -2209,6 +2209,16 @@ namespace ts {
|
||||
name: string;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
/**
|
||||
* Subset of properties from SourceFile that are used in multiple utility functions
|
||||
*/
|
||||
export interface SourceFileLike {
|
||||
readonly text: string;
|
||||
lineMap: number[];
|
||||
}
|
||||
|
||||
|
||||
// Source files are declarations when they are external modules.
|
||||
export interface SourceFile extends Declaration {
|
||||
kind: SyntaxKind.SourceFile;
|
||||
@@ -4138,6 +4148,8 @@ namespace ts {
|
||||
/*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;
|
||||
/*@internal*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void;
|
||||
/*@internal*/ onSetSourceFile?: (node: SourceFile) => void;
|
||||
/*@internal*/ onBeforeEmitNodeArray?: (nodes: NodeArray<any>) => void;
|
||||
/*@internal*/ onAfterEmitNodeArray?: (nodes: NodeArray<any>) => void;
|
||||
}
|
||||
|
||||
export interface PrinterOptions {
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getStartPositionOfLine(line: number, sourceFile: SourceFile): number {
|
||||
export function getStartPositionOfLine(line: number, sourceFile: SourceFileLike): number {
|
||||
Debug.assert(line >= 0);
|
||||
return getLineStarts(sourceFile)[line];
|
||||
}
|
||||
@@ -204,7 +204,7 @@ namespace ts {
|
||||
return value !== undefined;
|
||||
}
|
||||
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFileLike): number {
|
||||
Debug.assert(line >= 0);
|
||||
const lineStarts = getLineStarts(sourceFile);
|
||||
|
||||
@@ -255,7 +255,11 @@ namespace ts {
|
||||
return !nodeIsMissing(node);
|
||||
}
|
||||
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile, includeJsDoc?: boolean): number {
|
||||
export function isToken(n: Node): boolean {
|
||||
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
|
||||
}
|
||||
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, includeJsDoc?: boolean): number {
|
||||
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
|
||||
// want to skip trivia because this will launch us forward to the next token.
|
||||
if (nodeIsMissing(node)) {
|
||||
@@ -289,7 +293,7 @@ namespace ts {
|
||||
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
}
|
||||
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number {
|
||||
if (nodeIsMissing(node) || !node.decorators) {
|
||||
return getTokenPosOfNode(node, sourceFile);
|
||||
}
|
||||
@@ -2491,7 +2495,7 @@ namespace ts {
|
||||
return indentStrings[1].length;
|
||||
}
|
||||
|
||||
export function createTextWriter(newLine: String): EmitTextWriter {
|
||||
export function createTextWriter(newLine: string): EmitTextWriter {
|
||||
let output: string;
|
||||
let indent: number;
|
||||
let lineStart: boolean;
|
||||
|
||||
+75
-75
@@ -154,9 +154,9 @@ namespace ts {
|
||||
* Starts a new lexical environment and visits a parameter list, suspending the lexical
|
||||
* environment upon completion.
|
||||
*/
|
||||
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: Visitor, context: TransformationContext) {
|
||||
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
|
||||
context.startLexicalEnvironment();
|
||||
const updated = visitNodes(nodes, visitor, isParameterDeclaration);
|
||||
const updated = nodesVisitor(nodes, visitor, isParameterDeclaration);
|
||||
context.suspendLexicalEnvironment();
|
||||
return updated;
|
||||
}
|
||||
@@ -204,9 +204,9 @@ namespace ts {
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @param context A lexical environment context for the visitor.
|
||||
*/
|
||||
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext): T | undefined;
|
||||
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): T | undefined;
|
||||
|
||||
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext): Node {
|
||||
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes): Node {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -243,8 +243,8 @@ namespace ts {
|
||||
// Signature elements
|
||||
case SyntaxKind.Parameter:
|
||||
return updateParameter(<ParameterDeclaration>node,
|
||||
visitNodes((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||
(<ParameterDeclaration>node).dotDotDotToken,
|
||||
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
|
||||
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode),
|
||||
@@ -257,55 +257,55 @@ namespace ts {
|
||||
// Type member
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return updateProperty(<PropertyDeclaration>node,
|
||||
visitNodes((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<PropertyDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<PropertyDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<PropertyDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNode((<PropertyDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<PropertyDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return updateMethod(<MethodDeclaration>node,
|
||||
visitNodes((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||
(<MethodDeclaration>node).asteriskToken,
|
||||
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNodes((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context),
|
||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<MethodDeclaration>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
return updateConstructor(<ConstructorDeclaration>node,
|
||||
visitNodes((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context),
|
||||
nodesVisitor((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<ConstructorDeclaration>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
return updateGetAccessor(<GetAccessorDeclaration>node,
|
||||
visitNodes((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<GetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context),
|
||||
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<GetAccessorDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<GetAccessorDeclaration>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
return updateSetAccessor(<SetAccessorDeclaration>node,
|
||||
visitNodes((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<SetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context),
|
||||
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<SetAccessorDeclaration>node).body, visitor, context));
|
||||
|
||||
// Binding patterns
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return updateObjectBindingPattern(<ObjectBindingPattern>node,
|
||||
visitNodes((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
|
||||
nodesVisitor((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
|
||||
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return updateArrayBindingPattern(<ArrayBindingPattern>node,
|
||||
visitNodes((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
|
||||
nodesVisitor((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
return updateBindingElement(<BindingElement>node,
|
||||
@@ -317,11 +317,11 @@ namespace ts {
|
||||
// Expression
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return updateArrayLiteral(<ArrayLiteralExpression>node,
|
||||
visitNodes((<ArrayLiteralExpression>node).elements, visitor, isExpression));
|
||||
nodesVisitor((<ArrayLiteralExpression>node).elements, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return updateObjectLiteral(<ObjectLiteralExpression>node,
|
||||
visitNodes((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
|
||||
nodesVisitor((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
|
||||
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return updatePropertyAccess(<PropertyAccessExpression>node,
|
||||
@@ -336,14 +336,14 @@ namespace ts {
|
||||
case SyntaxKind.CallExpression:
|
||||
return updateCall(<CallExpression>node,
|
||||
visitNode((<CallExpression>node).expression, visitor, isExpression),
|
||||
visitNodes((<CallExpression>node).typeArguments, visitor, isTypeNode),
|
||||
visitNodes((<CallExpression>node).arguments, visitor, isExpression));
|
||||
nodesVisitor((<CallExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<CallExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NewExpression:
|
||||
return updateNew(<NewExpression>node,
|
||||
visitNode((<NewExpression>node).expression, visitor, isExpression),
|
||||
visitNodes((<NewExpression>node).typeArguments, visitor, isTypeNode),
|
||||
visitNodes((<NewExpression>node).arguments, visitor, isExpression));
|
||||
nodesVisitor((<NewExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<NewExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
return updateTaggedTemplate(<TaggedTemplateExpression>node,
|
||||
@@ -361,19 +361,19 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return updateFunctionExpression(<FunctionExpression>node,
|
||||
visitNodes((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||
(<FunctionExpression>node).asteriskToken,
|
||||
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
|
||||
visitNodes((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context),
|
||||
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionExpression>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return updateArrowFunction(<ArrowFunction>node,
|
||||
visitNodes((<ArrowFunction>node).modifiers, visitor, isModifier),
|
||||
visitNodes((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<ArrowFunction>node).parameters, visitor, context),
|
||||
nodesVisitor((<ArrowFunction>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace ts {
|
||||
case SyntaxKind.TemplateExpression:
|
||||
return updateTemplateExpression(<TemplateExpression>node,
|
||||
visitNode((<TemplateExpression>node).head, visitor, isTemplateHead),
|
||||
visitNodes((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
|
||||
nodesVisitor((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
|
||||
|
||||
case SyntaxKind.YieldExpression:
|
||||
return updateYield(<YieldExpression>node,
|
||||
@@ -428,15 +428,15 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ClassExpression:
|
||||
return updateClassExpression(<ClassExpression>node,
|
||||
visitNodes((<ClassExpression>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ClassExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassExpression>node).name, visitor, isIdentifier),
|
||||
visitNodes((<ClassExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
visitNodes((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
|
||||
visitNodes((<ClassExpression>node).members, visitor, isClassElement));
|
||||
nodesVisitor((<ClassExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassExpression>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return updateExpressionWithTypeArguments(<ExpressionWithTypeArguments>node,
|
||||
visitNodes((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<ExpressionWithTypeArguments>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.AsExpression:
|
||||
@@ -457,11 +457,11 @@ namespace ts {
|
||||
// Element
|
||||
case SyntaxKind.Block:
|
||||
return updateBlock(<Block>node,
|
||||
visitNodes((<Block>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<Block>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
return updateVariableStatement(<VariableStatement>node,
|
||||
visitNodes((<VariableStatement>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<VariableStatement>node).modifiers, visitor, isModifier),
|
||||
visitNode((<VariableStatement>node).declarationList, visitor, isVariableDeclarationList));
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
@@ -549,61 +549,61 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
return updateVariableDeclarationList(<VariableDeclarationList>node,
|
||||
visitNodes((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
|
||||
nodesVisitor((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return updateFunctionDeclaration(<FunctionDeclaration>node,
|
||||
visitNodes((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||
(<FunctionDeclaration>node).asteriskToken,
|
||||
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNodes((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context),
|
||||
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return updateClassDeclaration(<ClassDeclaration>node,
|
||||
visitNodes((<ClassDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ClassDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ClassDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ClassDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNodes((<ClassDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
visitNodes((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
visitNodes((<ClassDeclaration>node).members, visitor, isClassElement));
|
||||
nodesVisitor((<ClassDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassDeclaration>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return updateEnumDeclaration(<EnumDeclaration>node,
|
||||
visitNodes((<EnumDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<EnumDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<EnumDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<EnumDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<EnumDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNodes((<EnumDeclaration>node).members, visitor, isEnumMember));
|
||||
nodesVisitor((<EnumDeclaration>node).members, visitor, isEnumMember));
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return updateModuleDeclaration(<ModuleDeclaration>node,
|
||||
visitNodes((<ModuleDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ModuleDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ModuleDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ModuleDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ModuleDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ModuleDeclaration>node).body, visitor, isModuleBody));
|
||||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return updateModuleBlock(<ModuleBlock>node,
|
||||
visitNodes((<ModuleBlock>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<ModuleBlock>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.CaseBlock:
|
||||
return updateCaseBlock(<CaseBlock>node,
|
||||
visitNodes((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
|
||||
nodesVisitor((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return updateImportEqualsDeclaration(<ImportEqualsDeclaration>node,
|
||||
visitNodes((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).moduleReference, visitor, isModuleReference));
|
||||
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return updateImportDeclaration(<ImportDeclaration>node,
|
||||
visitNodes((<ImportDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ImportDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ImportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportDeclaration>node).importClause, visitor, isImportClause),
|
||||
visitNode((<ImportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
@@ -618,7 +618,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.NamedImports:
|
||||
return updateNamedImports(<NamedImports>node,
|
||||
visitNodes((<NamedImports>node).elements, visitor, isImportSpecifier));
|
||||
nodesVisitor((<NamedImports>node).elements, visitor, isImportSpecifier));
|
||||
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
return updateImportSpecifier(<ImportSpecifier>node,
|
||||
@@ -627,20 +627,20 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return updateExportAssignment(<ExportAssignment>node,
|
||||
visitNodes((<ExportAssignment>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ExportAssignment>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ExportAssignment>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportAssignment>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportAssignment>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return updateExportDeclaration(<ExportDeclaration>node,
|
||||
visitNodes((<ExportDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ExportDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ExportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportDeclaration>node).exportClause, visitor, isNamedExports),
|
||||
visitNode((<ExportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NamedExports:
|
||||
return updateNamedExports(<NamedExports>node,
|
||||
visitNodes((<NamedExports>node).elements, visitor, isExportSpecifier));
|
||||
nodesVisitor((<NamedExports>node).elements, visitor, isExportSpecifier));
|
||||
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return updateExportSpecifier(<ExportSpecifier>node,
|
||||
@@ -656,12 +656,12 @@ namespace ts {
|
||||
case SyntaxKind.JsxElement:
|
||||
return updateJsxElement(<JsxElement>node,
|
||||
visitNode((<JsxElement>node).openingElement, visitor, isJsxOpeningElement),
|
||||
visitNodes((<JsxElement>node).children, visitor, isJsxChild),
|
||||
nodesVisitor((<JsxElement>node).children, visitor, isJsxChild),
|
||||
visitNode((<JsxElement>node).closingElement, visitor, isJsxClosingElement));
|
||||
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return updateJsxAttributes(<JsxAttributes>node,
|
||||
visitNodes((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
|
||||
nodesVisitor((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
|
||||
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
|
||||
@@ -694,15 +694,15 @@ namespace ts {
|
||||
case SyntaxKind.CaseClause:
|
||||
return updateCaseClause(<CaseClause>node,
|
||||
visitNode((<CaseClause>node).expression, visitor, isExpression),
|
||||
visitNodes((<CaseClause>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<CaseClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.DefaultClause:
|
||||
return updateDefaultClause(<DefaultClause>node,
|
||||
visitNodes((<DefaultClause>node).statements, visitor, isStatement));
|
||||
nodesVisitor((<DefaultClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
return updateHeritageClause(<HeritageClause>node,
|
||||
visitNodes((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
|
||||
nodesVisitor((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
return updateCatchClause(<CatchClause>node,
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
namespace FourSlash {
|
||||
ts.disableIncrementalParsing = false;
|
||||
|
||||
function normalizeNewLines(s: string) {
|
||||
return s.replace(/\r\n/g, "\n");
|
||||
}
|
||||
|
||||
// Represents a parsed source file with metadata
|
||||
export interface FourSlashFile {
|
||||
// The contents of the file (with markers, etc stripped out)
|
||||
@@ -1958,8 +1962,7 @@ namespace FourSlash {
|
||||
|
||||
public verifyCurrentFileContent(text: string) {
|
||||
const actual = this.getFileContent(this.activeFile.fileName);
|
||||
const replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n");
|
||||
if (replaceNewlines(actual) !== replaceNewlines(text)) {
|
||||
if (normalizeNewLines(actual) !== normalizeNewLines(text)) {
|
||||
throw new Error("verifyCurrentFileContent\n" +
|
||||
"\tExpected: \"" + text + "\"\n" +
|
||||
"\t Actual: \"" + actual + "\"");
|
||||
@@ -2135,7 +2138,7 @@ namespace FourSlash {
|
||||
const actualText = this.rangeText(ranges[0]);
|
||||
|
||||
const result = includeWhiteSpace
|
||||
? actualText === expectedText
|
||||
? normalizeNewLines(actualText) === normalizeNewLines(expectedText)
|
||||
: this.removeWhitespace(actualText) === this.removeWhitespace(expectedText);
|
||||
|
||||
if (!result) {
|
||||
@@ -2185,7 +2188,7 @@ namespace FourSlash {
|
||||
continue;
|
||||
}
|
||||
|
||||
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
|
||||
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code], this.formatCodeSettings);
|
||||
if (newActions && newActions.length) {
|
||||
actions = actions ? actions.concat(newActions) : newActions;
|
||||
}
|
||||
@@ -2248,22 +2251,23 @@ namespace FourSlash {
|
||||
|
||||
if (expected === undefined) {
|
||||
if (actual) {
|
||||
this.raiseError(name + " failed - expected no template but got {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "}");
|
||||
this.raiseError(`${name} failed - expected no template but got {newText: "${actual.newText}", caretOffset: ${actual.caretOffset}}`);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (actual === undefined) {
|
||||
this.raiseError(name + " failed - expected the template {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "} but got nothing instead");
|
||||
this.raiseError(`${name} failed - expected the template {newText: "${expected.newText}", caretOffset: "${expected.caretOffset}"} but got nothing instead`);
|
||||
|
||||
}
|
||||
|
||||
if (actual.newText !== expected.newText) {
|
||||
this.raiseError(name + " failed - expected insertion:\n" + this.clarifyNewlines(expected.newText) + "\nactual insertion:\n" + this.clarifyNewlines(actual.newText));
|
||||
this.raiseError(`${name} failed - expected insertion:\n"${this.clarifyNewlines(expected.newText)}"\nactual insertion:\n"${this.clarifyNewlines(actual.newText)}"`);
|
||||
}
|
||||
|
||||
if (actual.caretOffset !== expected.caretOffset) {
|
||||
this.raiseError(name + " failed - expected caretOffset: " + expected.caretOffset + ",\nactual caretOffset:" + actual.caretOffset);
|
||||
this.raiseError(`${name} failed - expected caretOffset: ${expected.caretOffset}\nactual caretOffset:${actual.caretOffset}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
"./unittests/projectErrors.ts",
|
||||
"./unittests/printer.ts",
|
||||
"./unittests/transform.ts",
|
||||
"./unittests/customTransforms.ts"
|
||||
"./unittests/customTransforms.ts",
|
||||
"./unittests/textChanges.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,791 @@
|
||||
/// <reference path="..\..\compiler\emitter.ts" />
|
||||
/// <reference path="..\..\services\textChanges.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe("textChanges", () => {
|
||||
function findChild(name: string, n: Node) {
|
||||
return find(n);
|
||||
|
||||
function find(node: Node): Node {
|
||||
if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.text === name) {
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
return forEachChild(node, find);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const printerOptions = { newLine: NewLineKind.LineFeed };
|
||||
const newLineCharacter = getNewLineCharacter(printerOptions);
|
||||
|
||||
function getRuleProvider(action?: (opts: FormatCodeSettings) => void) {
|
||||
const options = {
|
||||
indentSize: 4,
|
||||
tabSize: 4,
|
||||
newLineCharacter,
|
||||
convertTabsToSpaces: true,
|
||||
indentStyle: ts.IndentStyle.Smart,
|
||||
insertSpaceAfterConstructor: false,
|
||||
insertSpaceAfterCommaDelimiter: true,
|
||||
insertSpaceAfterSemicolonInForStatements: true,
|
||||
insertSpaceBeforeAndAfterBinaryOperators: true,
|
||||
insertSpaceAfterKeywordsInControlFlowStatements: true,
|
||||
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
|
||||
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
|
||||
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
|
||||
insertSpaceBeforeFunctionParenthesis: false,
|
||||
placeOpenBraceOnNewLineForFunctions: false,
|
||||
placeOpenBraceOnNewLineForControlBlocks: false,
|
||||
};
|
||||
if (action) {
|
||||
action(options);
|
||||
}
|
||||
const rulesProvider = new formatting.RulesProvider();
|
||||
rulesProvider.ensureUpToDate(options);
|
||||
return rulesProvider;
|
||||
}
|
||||
|
||||
// validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed.
|
||||
function verifyPositions({ text, node }: textChanges.NonFormattedText): void {
|
||||
const nodeList = flattenNodes(node);
|
||||
const sourceFile = createSourceFile("f.ts", text, ScriptTarget.ES2015);
|
||||
const parsedNodeList = flattenNodes(sourceFile.statements[0]);
|
||||
Debug.assert(nodeList.length === parsedNodeList.length);
|
||||
for (let i = 0; i < nodeList.length; i++) {
|
||||
const left = nodeList[i];
|
||||
const right = parsedNodeList[i];
|
||||
Debug.assert(left.pos === right.pos);
|
||||
Debug.assert(left.end === right.end);
|
||||
}
|
||||
|
||||
function flattenNodes(n: Node) {
|
||||
const data: (Node | NodeArray<any>)[] = [];
|
||||
walk(n);
|
||||
return data;
|
||||
|
||||
function walk(n: Node | Node[]): void {
|
||||
data.push(<any>n);
|
||||
return isArray(n) ? forEach(n, walk) : forEachChild(n, walk, walk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function runSingleFileTest(caption: string, setupFormatOptions: (opts: FormatCodeSettings) => void, text: string, validateNodes: boolean, testBlock: (sourceFile: SourceFile, changeTracker: textChanges.ChangeTracker) => void) {
|
||||
it(caption, () => {
|
||||
Harness.Baseline.runBaseline(`textChanges/${caption}.js`, () => {
|
||||
const sourceFile = createSourceFile("source.ts", text, ScriptTarget.ES2015, /*setParentNodes*/ true);
|
||||
const rulesProvider = getRuleProvider(setupFormatOptions);
|
||||
const changeTracker = new textChanges.ChangeTracker(printerOptions.newLine, rulesProvider, validateNodes ? verifyPositions : undefined);
|
||||
testBlock(sourceFile, changeTracker);
|
||||
const changes = changeTracker.getChanges();
|
||||
assert.equal(changes.length, 1);
|
||||
assert.equal(changes[0].fileName, sourceFile.fileName);
|
||||
const modified = textChanges.applyChanges(sourceFile.text, changes[0].textChanges);
|
||||
return `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setNewLineForOpenBraceInFunctions(opts: FormatCodeSettings) {
|
||||
opts.placeOpenBraceOnNewLineForFunctions = true;
|
||||
}
|
||||
|
||||
{
|
||||
const text = `
|
||||
namespace M
|
||||
{
|
||||
namespace M2
|
||||
{
|
||||
function foo() {
|
||||
// comment 1
|
||||
const x = 1;
|
||||
|
||||
/**
|
||||
* comment 2 line 1
|
||||
* comment 2 line 2
|
||||
*/
|
||||
function f() {
|
||||
return 100;
|
||||
}
|
||||
const y = 2; // comment 3
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}`;
|
||||
runSingleFileTest("extractMethodLike", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
const statements = (<Block>(<FunctionDeclaration>findChild("foo", sourceFile)).body).statements.slice(1);
|
||||
const newFunction = createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ "bar",
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ emptyArray,
|
||||
/*type*/ createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*body */ createBlock(statements)
|
||||
);
|
||||
|
||||
changeTracker.insertNodeBefore(sourceFile, /*before*/findChild("M2", sourceFile), newFunction, { suffix: newLineCharacter });
|
||||
|
||||
// replace statements with return statement
|
||||
const newStatement = createReturn(
|
||||
createCall(
|
||||
/*expression*/ newFunction.name,
|
||||
/*typeArguments*/ undefined,
|
||||
/*argumentsArray*/ emptyArray
|
||||
));
|
||||
changeTracker.replaceNodeRange(sourceFile, statements[0], lastOrUndefined(statements), newStatement, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
function bar() {
|
||||
return 2;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("deleteRange1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteRange(sourceFile, { pos: text.indexOf("function foo"), end: text.indexOf("function bar") });
|
||||
});
|
||||
}
|
||||
function findVariableStatementContaining(name: string, sourceFile: SourceFile) {
|
||||
const varDecl = findChild(name, sourceFile);
|
||||
assert.equal(varDecl.kind, SyntaxKind.VariableDeclaration);
|
||||
const varStatement = varDecl.parent.parent;
|
||||
assert.equal(varStatement.kind, SyntaxKind.VariableStatement);
|
||||
return varStatement;
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
var x = 1; // some comment - 1
|
||||
/**
|
||||
* comment 2
|
||||
*/
|
||||
var y = 2; // comment 3
|
||||
var z = 3; // comment 4
|
||||
`;
|
||||
runSingleFileTest("deleteNode1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNode2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNode3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNode4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNode5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("x", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7
|
||||
`;
|
||||
runSingleFileTest("deleteNodeRange1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeRange2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
|
||||
{ useNonAdjustedStartPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNodeRange3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
|
||||
{ useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("deleteNodeRange4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
|
||||
{ useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
}
|
||||
function createTestVariableDeclaration(name: string) {
|
||||
return createVariableDeclaration(name, /*type*/ undefined, createObjectLiteral([createPropertyAssignment("p1", createLiteral(1))], /*multiline*/ true));
|
||||
}
|
||||
function createTestClass() {
|
||||
return createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
[
|
||||
createToken(SyntaxKind.PublicKeyword)
|
||||
],
|
||||
"class1",
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createHeritageClause(
|
||||
SyntaxKind.ImplementsKeyword,
|
||||
[
|
||||
createExpressionWithTypeArguments(/*typeArguments*/ undefined, createIdentifier("interface1"))
|
||||
]
|
||||
)
|
||||
],
|
||||
[
|
||||
createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
"property1",
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.BooleanKeyword),
|
||||
/*initializer*/ undefined
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("replaceRange", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceRangeWithForcedIndentation", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter, indentation: 8, delta: 0 });
|
||||
});
|
||||
|
||||
runSingleFileTest("replaceRangeNoLineBreakBefore", setNewLineForOpenBraceInFunctions, `const x = 1, y = "2";`, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createTestVariableDeclaration("z1");
|
||||
changeTracker.replaceRange(sourceFile, { pos: sourceFile.text.indexOf("y"), end: sourceFile.text.indexOf(";") }, newNode);
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace A {
|
||||
const x = 1, y = "2";
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("replaceNode1NoLineBreakBefore", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createTestVariableDeclaration("z1");
|
||||
changeTracker.replaceNode(sourceFile, findChild("y", sourceFile), newNode);
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("replaceNode1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNode2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNode3", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNode4", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
runSingleFileTest("replaceNode5", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y = 2; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("replaceNodeRange1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNodeRange2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNodeRange3", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("replaceNodeRange4", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7`;
|
||||
runSingleFileTest("insertNodeAt1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAt(sourceFile, text.indexOf("var y"), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeAt2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAt(sourceFile, text.indexOf("; // comment 4"), createTestVariableDeclaration("z1"));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace M {
|
||||
// comment 1
|
||||
var x = 1; // comment 2
|
||||
// comment 3
|
||||
var y; // comment 4
|
||||
var z = 3; // comment 5
|
||||
// comment 6
|
||||
var a = 4; // comment 7
|
||||
}`;
|
||||
runSingleFileTest("insertNodeBefore1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeBefore(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeBefore2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeBefore(sourceFile, findChild("M", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeAfter1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
|
||||
});
|
||||
runSingleFileTest("insertNodeAfter2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("M", sourceFile), createTestClass(), { prefix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
function findOpenBraceForConstructor(sourceFile: SourceFile) {
|
||||
const classDecl = <ClassDeclaration>sourceFile.statements[0];
|
||||
const constructorDecl = forEach(classDecl.members, m => m.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>m).body && <ConstructorDeclaration>m);
|
||||
return constructorDecl.body.getFirstToken();
|
||||
}
|
||||
function createTestSuperCall() {
|
||||
const superCall = createCall(
|
||||
createSuper(),
|
||||
/*typeArguments*/ undefined,
|
||||
/*argumentsArray*/ emptyArray
|
||||
);
|
||||
return createStatement(superCall);
|
||||
}
|
||||
const text1 = `
|
||||
class A {
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfter3", noop, text1, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findOpenBraceForConstructor(sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
|
||||
});
|
||||
const text2 = `
|
||||
class A {
|
||||
constructor() {
|
||||
var x = 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfter4", noop, text2, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
|
||||
});
|
||||
const text3 = `
|
||||
class A {
|
||||
constructor() {
|
||||
|
||||
}
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfter3-block with newline", noop, text3, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findOpenBraceForConstructor(sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `var a = 1, b = 2, c = 3;`;
|
||||
runSingleFileTest("deleteNodeInList1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `var a = 1,b = 2,c = 3;`;
|
||||
runSingleFileTest("deleteNodeInList1_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList2_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList3_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace M {
|
||||
var a = 1,
|
||||
b = 2,
|
||||
c = 3;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList6", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
namespace M {
|
||||
var a = 1, // comment 1
|
||||
// comment 2
|
||||
b = 2, // comment 3
|
||||
// comment 4
|
||||
c = 3; // comment 5
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList4_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList5_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList6_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo(a: number, b: string, c = true) {
|
||||
return 1;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList7", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList8", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList9", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo(a: number,b: string,c = true) {
|
||||
return 1;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList10", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList11", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList12", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
function foo(
|
||||
a: number,
|
||||
b: string,
|
||||
c = true) {
|
||||
return 1;
|
||||
}`;
|
||||
runSingleFileTest("deleteNodeInList13", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList14", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
|
||||
});
|
||||
runSingleFileTest("deleteNodeInList15", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const x = 1, y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const /*x*/ x = 1, /*y*/ y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const x = 1;`;
|
||||
runSingleFileTest("insertNodeInListAfter5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const x = 1,
|
||||
y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter6", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter7", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
const /*x*/ x = 1,
|
||||
/*y*/ y = 2;`;
|
||||
runSingleFileTest("insertNodeInListAfter8", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
runSingleFileTest("insertNodeInListAfter9", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter10", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter11", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter12", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter13", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter14", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter15", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter16", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0,
|
||||
x // this is x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter17", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
import {
|
||||
x0, x
|
||||
} from "bar"`;
|
||||
runSingleFileTest("insertNodeInListAfter18", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
|
||||
})
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x;
|
||||
}`;
|
||||
runSingleFileTest("insertNodeAfterMultipleNodes", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
let newNodes = [];
|
||||
for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) {
|
||||
newNodes.push(
|
||||
createProperty(undefined, undefined, i + "", undefined, undefined, undefined));
|
||||
}
|
||||
const insertAfter = findChild("x", sourceFile);
|
||||
for (const newNode of newNodes) {
|
||||
changeTracker.insertNodeAfter(sourceFile, insertAfter, newNode, { suffix: newLineCharacter });
|
||||
}
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfterInClass1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined), { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("insertNodeAfterInClass2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined), { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x;
|
||||
y = 1;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("deleteNodeAfterInClass1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findChild("x", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x
|
||||
y = 1;
|
||||
}
|
||||
`;
|
||||
runSingleFileTest("deleteNodeAfterInClass2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
changeTracker.deleteNode(sourceFile, findChild("x", sourceFile));
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x = foo
|
||||
}
|
||||
`
|
||||
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
class A {
|
||||
x() {
|
||||
}
|
||||
}
|
||||
`
|
||||
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
interface A {
|
||||
x
|
||||
}
|
||||
`
|
||||
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
interface A {
|
||||
x()
|
||||
}
|
||||
`
|
||||
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createComputedPropertyName(createLiteral(1)),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword),
|
||||
/*initializer*/ undefined);
|
||||
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
{
|
||||
const text = `
|
||||
let x = foo
|
||||
`
|
||||
runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
|
||||
const newNode = createStatement(createParen(createLiteral(1)));
|
||||
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode, { suffix: newLineCharacter });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
Vendored
+44
@@ -5,9 +5,53 @@ interface DOMTokenList {
|
||||
}
|
||||
|
||||
interface NodeList {
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list
|
||||
*/
|
||||
entries(): IterableIterator<[number, Node]>;
|
||||
/**
|
||||
* Performs the specified action for each node in an list.
|
||||
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: Node, index: number, listObj: NodeList) => void, thisArg?: any): void;
|
||||
/**
|
||||
* Returns an list of keys in the list
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the list
|
||||
*/
|
||||
values(): IterableIterator<Node>;
|
||||
|
||||
|
||||
[Symbol.iterator](): IterableIterator<Node>
|
||||
}
|
||||
|
||||
interface NodeListOf<TNode extends Node> {
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list
|
||||
*/
|
||||
entries(): IterableIterator<[number, TNode]>;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each node in an list.
|
||||
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: TNode, index: number, listObj: NodeListOf<TNode>) => void, thisArg?: any): void;
|
||||
/**
|
||||
* Returns an list of keys in the list
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
* Returns an list of values in the list
|
||||
*/
|
||||
values(): IterableIterator<TNode>;
|
||||
|
||||
[Symbol.iterator](): IterableIterator<TNode>
|
||||
}
|
||||
|
||||
Vendored
+15
-5
@@ -10,7 +10,9 @@ interface Array<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): T | undefined;
|
||||
find<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -21,7 +23,9 @@ interface Array<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -52,7 +56,9 @@ interface ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: undefined, v: T, k: number) => U): Array<U>;
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: undefined, v: T, k: number) => U, thisArg: undefined): Array<U>;
|
||||
from<Z, T, U>(arrayLike: ArrayLike<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
|
||||
|
||||
|
||||
/**
|
||||
@@ -357,7 +363,9 @@ interface ReadonlyArray<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg?: any): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: ReadonlyArray<T>) => boolean): T | undefined;
|
||||
find(predicate: (this: undefined, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: undefined): T | undefined;
|
||||
find<Z>(predicate: (this: Z, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: Z): T | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -368,7 +376,9 @@ interface ReadonlyArray<T> {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
|
||||
Vendored
+48
-10
@@ -54,7 +54,9 @@ interface ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
|
||||
from<T, U>(iterable: Iterable<T>, mapfn: (this: undefined, v: T, k: number) => U): Array<U>;
|
||||
from<T, U>(iterable: Iterable<T>, mapfn: (this: undefined, v: T, k: number) => U, thisArg: undefined): Array<U>;
|
||||
from<Z, T, U>(iterable: Iterable<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
@@ -180,7 +182,11 @@ interface Int8ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int8Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Int8Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,7 +218,11 @@ interface Uint8ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint8Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +257,11 @@ interface Uint8ClampedArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8ClampedArray;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint8ClampedArray;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +295,11 @@ interface Int16ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int16Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Int16Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,7 +331,11 @@ interface Uint16ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint16Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint16Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint16Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,7 +367,11 @@ interface Int32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int32Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Int32Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,7 +403,11 @@ interface Uint32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint32Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Uint32Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -409,7 +439,11 @@ interface Float32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Float32Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float32Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Float32Array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,5 +475,9 @@ interface Float64ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Float64Array;
|
||||
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float64Array;
|
||||
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array;
|
||||
|
||||
from(arrayLike: Iterable<number>): Float64Array;
|
||||
}
|
||||
|
||||
Vendored
+286
-127
@@ -325,53 +325,27 @@ interface String {
|
||||
* Matches a string with a regular expression, and returns an array containing the results of that search.
|
||||
* @param regexp A variable name or string literal containing the regular expression pattern and flags.
|
||||
*/
|
||||
match(regexp: string): RegExpMatchArray | null;
|
||||
|
||||
/**
|
||||
* Matches a string with a regular expression, and returns an array containing the results of that search.
|
||||
* @param regexp A regular expression object that contains the regular expression pattern and applicable flags.
|
||||
*/
|
||||
match(regexp: RegExp): RegExpMatchArray | null;
|
||||
match(regexp: string | RegExp): RegExpMatchArray | null;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using a regular expression or search string.
|
||||
* @param searchValue A string to search for.
|
||||
* @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
|
||||
*/
|
||||
replace(searchValue: string, replaceValue: string): string;
|
||||
replace(searchValue: string | RegExp, replaceValue: string): string;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using a regular expression or search string.
|
||||
* @param searchValue A string to search for.
|
||||
* @param replacer A function that returns the replacement text.
|
||||
*/
|
||||
replace(searchValue: string, replacer: (substring: string, ...args: any[]) => string): string;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using a regular expression or search string.
|
||||
* @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags.
|
||||
* @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
|
||||
*/
|
||||
replace(searchValue: RegExp, replaceValue: string): string;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using a regular expression or search string.
|
||||
* @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags
|
||||
* @param replacer A function that returns the replacement text.
|
||||
*/
|
||||
replace(searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string;
|
||||
replace(searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string;
|
||||
|
||||
/**
|
||||
* Finds the first substring match in a regular expression search.
|
||||
* @param regexp The regular expression pattern and applicable flags.
|
||||
*/
|
||||
search(regexp: string): number;
|
||||
|
||||
/**
|
||||
* Finds the first substring match in a regular expression search.
|
||||
* @param regexp The regular expression pattern and applicable flags.
|
||||
*/
|
||||
search(regexp: RegExp): number;
|
||||
search(regexp: string | RegExp): number;
|
||||
|
||||
/**
|
||||
* Returns a section of a string.
|
||||
@@ -386,14 +360,7 @@ interface String {
|
||||
* @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
|
||||
* @param limit A value used to limit the number of elements returned in the array.
|
||||
*/
|
||||
split(separator: string, limit?: number): string[];
|
||||
|
||||
/**
|
||||
* Split a string into substrings using the specified separator and return them as an array.
|
||||
* @param separator A Regular Express that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
|
||||
* @param limit A value used to limit the number of elements returned in the array.
|
||||
*/
|
||||
split(separator: RegExp, limit?: number): string[];
|
||||
split(separator: string | RegExp, limit?: number): string[];
|
||||
|
||||
/**
|
||||
* Returns the substring at the specified location within a String object.
|
||||
@@ -861,9 +828,9 @@ interface RegExp {
|
||||
}
|
||||
|
||||
interface RegExpConstructor {
|
||||
new (pattern: RegExp): RegExp;
|
||||
new (pattern: RegExp | string): RegExp;
|
||||
new (pattern: string, flags?: string): RegExp;
|
||||
(pattern: RegExp): RegExp;
|
||||
(pattern: RegExp | string): RegExp;
|
||||
(pattern: string, flags?: string): RegExp;
|
||||
readonly prototype: RegExp;
|
||||
|
||||
@@ -1050,37 +1017,49 @@ interface ReadonlyArray<T> {
|
||||
* @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: Z): boolean;
|
||||
/**
|
||||
* Determines whether the specified callback function returns true for any element of an array.
|
||||
* @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: Z): boolean;
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => void, thisArg: Z): void;
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
||||
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => U, thisArg?: any): U[];
|
||||
map<U>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => U): U[];
|
||||
map<U>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => U, thisArg: undefined): U[];
|
||||
map<Z, U>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => U, thisArg: Z): U[];
|
||||
/**
|
||||
* Returns the elements of an array that meet the condition specified in a callback function.
|
||||
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter<S extends T>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg?: any): S[];
|
||||
filter<S extends T>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => value is S): S[];
|
||||
filter<S extends T>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg: undefined): S[];
|
||||
filter<Z, S extends T>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg: Z): S[];
|
||||
/**
|
||||
* Returns the elements of an array that meet the condition specified in a callback function.
|
||||
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => any, thisArg?: any): T[];
|
||||
filter(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => any): T[];
|
||||
filter(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => any, thisArg: undefined): T[];
|
||||
filter<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => any, thisArg: Z): T[];
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
|
||||
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
|
||||
@@ -1197,55 +1176,73 @@ interface Array<T> {
|
||||
* @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean;
|
||||
/**
|
||||
* Determines whether the specified callback function returns true for any element of an array.
|
||||
* @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean;
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: T, index: number, array: T[]) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: T, index: number, array: T[]) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => void, thisArg: Z): void;
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
||||
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map<U>(this: [T, T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U, U];
|
||||
map<U>(this: [T, T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U, U, U, U];
|
||||
map<U>(this: [T, T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U, U];
|
||||
map<Z, U>(this: [T, T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U, U];
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
||||
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map<U>(this: [T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U];
|
||||
map<U>(this: [T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U, U, U];
|
||||
map<U>(this: [T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U];
|
||||
map<Z, U>(this: [T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U];
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
||||
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map<U>(this: [T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U];
|
||||
map<U>(this: [T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U, U];
|
||||
map<U>(this: [T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U];
|
||||
map<Z, U>(this: [T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U];
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
||||
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map<U>(this: [T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U];
|
||||
map<U>(this: [T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U];
|
||||
map<U>(this: [T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U];
|
||||
map<Z, U>(this: [T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U];
|
||||
/**
|
||||
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
||||
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
|
||||
map<U>(callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): U[];
|
||||
map<U>(callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): U[];
|
||||
map<Z, U>(callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): U[];
|
||||
/**
|
||||
* Returns the elements of an array that meet the condition specified in a callback function.
|
||||
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[];
|
||||
filter(callbackfn: (this: undefined, value: T, index: number, array: T[]) => any): T[];
|
||||
filter(callbackfn: (this: undefined, value: T, index: number, array: T[]) => any, thisArg: undefined): T[];
|
||||
filter<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => any, thisArg: Z): T[];
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
|
||||
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
|
||||
@@ -1590,7 +1587,9 @@ interface Int8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -1609,7 +1608,9 @@ interface Int8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Int8Array) => any, thisArg?: any): Int8Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => any): Int8Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => any, thisArg: undefined): Int8Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => any, thisArg: Z): Int8Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -1620,7 +1621,9 @@ interface Int8Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -1631,7 +1634,9 @@ interface Int8Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -1640,7 +1645,9 @@ interface Int8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -1678,7 +1685,9 @@ interface Int8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => number): Int8Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => number, thisArg: undefined): Int8Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => number, thisArg: Z): Int8Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -1762,7 +1771,9 @@ interface Int8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -1814,7 +1825,11 @@ interface Int8ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Int8Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int8Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Int8Array;
|
||||
|
||||
}
|
||||
declare const Int8Array: Int8ArrayConstructor;
|
||||
@@ -1863,7 +1878,9 @@ interface Uint8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -1882,7 +1899,9 @@ interface Uint8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Uint8Array) => any, thisArg?: any): Uint8Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => any): Uint8Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => any, thisArg: undefined): Uint8Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => any, thisArg: Z): Uint8Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -1893,7 +1912,9 @@ interface Uint8Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -1904,7 +1925,9 @@ interface Uint8Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -1913,7 +1936,9 @@ interface Uint8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -1951,7 +1976,9 @@ interface Uint8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => number): Uint8Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => number, thisArg: undefined): Uint8Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => number, thisArg: Z): Uint8Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -2035,7 +2062,9 @@ interface Uint8Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -2088,7 +2117,11 @@ interface Uint8ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Uint8Array;
|
||||
|
||||
}
|
||||
declare const Uint8Array: Uint8ArrayConstructor;
|
||||
@@ -2137,7 +2170,9 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -2156,7 +2191,9 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => any, thisArg?: any): Uint8ClampedArray;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => any): Uint8ClampedArray;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => any, thisArg: undefined): Uint8ClampedArray;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => any, thisArg: Z): Uint8ClampedArray;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -2167,7 +2204,9 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -2178,7 +2217,9 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -2187,7 +2228,9 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -2225,7 +2268,9 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => number): Uint8ClampedArray;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => number, thisArg: undefined): Uint8ClampedArray;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => number, thisArg: Z): Uint8ClampedArray;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -2309,7 +2354,9 @@ interface Uint8ClampedArray {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -2362,7 +2409,11 @@ interface Uint8ClampedArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8ClampedArray;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Uint8ClampedArray;
|
||||
}
|
||||
declare const Uint8ClampedArray: Uint8ClampedArrayConstructor;
|
||||
|
||||
@@ -2410,7 +2461,9 @@ interface Int16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -2429,7 +2482,9 @@ interface Int16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Int16Array) => any, thisArg?: any): Int16Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => any): Int16Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => any, thisArg: undefined): Int16Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => any, thisArg: Z): Int16Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -2440,7 +2495,9 @@ interface Int16Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -2451,7 +2508,9 @@ interface Int16Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -2460,7 +2519,9 @@ interface Int16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Int16Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -2498,7 +2559,9 @@ interface Int16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => number): Int16Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => number, thisArg: undefined): Int16Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => number, thisArg: Z): Int16Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -2582,7 +2645,9 @@ interface Int16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -2635,7 +2700,11 @@ interface Int16ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Int16Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int16Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Int16Array;
|
||||
|
||||
}
|
||||
declare const Int16Array: Int16ArrayConstructor;
|
||||
@@ -2684,7 +2753,9 @@ interface Uint16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -2703,7 +2774,9 @@ interface Uint16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Uint16Array) => any, thisArg?: any): Uint16Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => any): Uint16Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => any, thisArg: undefined): Uint16Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => any, thisArg: Z): Uint16Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -2714,7 +2787,9 @@ interface Uint16Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -2725,7 +2800,9 @@ interface Uint16Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -2734,7 +2811,9 @@ interface Uint16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -2772,7 +2851,9 @@ interface Uint16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => number): Uint16Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => number, thisArg: undefined): Uint16Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => number, thisArg: Z): Uint16Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -2856,7 +2937,9 @@ interface Uint16Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -2909,7 +2992,11 @@ interface Uint16ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint16Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint16Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Uint16Array;
|
||||
|
||||
}
|
||||
declare const Uint16Array: Uint16ArrayConstructor;
|
||||
@@ -2957,7 +3044,9 @@ interface Int32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -2976,7 +3065,9 @@ interface Int32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Int32Array) => any, thisArg?: any): Int32Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => any): Int32Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => any, thisArg: undefined): Int32Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => any, thisArg: Z): Int32Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -2987,7 +3078,9 @@ interface Int32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -2998,7 +3091,9 @@ interface Int32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -3007,7 +3102,9 @@ interface Int32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Int32Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -3045,7 +3142,9 @@ interface Int32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Int32Array) => number, thisArg?: any): Int32Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => number): Int32Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => number, thisArg: undefined): Int32Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => number, thisArg: Z): Int32Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -3129,7 +3228,9 @@ interface Int32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -3182,7 +3283,11 @@ interface Int32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Int32Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int32Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Int32Array;
|
||||
}
|
||||
declare const Int32Array: Int32ArrayConstructor;
|
||||
|
||||
@@ -3230,7 +3335,9 @@ interface Uint32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -3249,7 +3356,9 @@ interface Uint32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Uint32Array) => any, thisArg?: any): Uint32Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => any): Uint32Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => any, thisArg: undefined): Uint32Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => any, thisArg: Z): Uint32Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -3260,7 +3369,9 @@ interface Uint32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -3271,7 +3382,9 @@ interface Uint32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -3280,7 +3393,9 @@ interface Uint32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -3318,7 +3433,9 @@ interface Uint32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => number): Uint32Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => number, thisArg: undefined): Uint32Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => number, thisArg: Z): Uint32Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -3402,7 +3519,9 @@ interface Uint32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -3455,7 +3574,11 @@ interface Uint32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint32Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint32Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Uint32Array;
|
||||
}
|
||||
declare const Uint32Array: Uint32ArrayConstructor;
|
||||
|
||||
@@ -3503,7 +3626,9 @@ interface Float32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -3522,7 +3647,9 @@ interface Float32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Float32Array) => any, thisArg?: any): Float32Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => any): Float32Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => any, thisArg: undefined): Float32Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => any, thisArg: Z): Float32Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -3533,7 +3660,9 @@ interface Float32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -3544,7 +3673,9 @@ interface Float32Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -3553,7 +3684,9 @@ interface Float32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Float32Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -3591,7 +3724,9 @@ interface Float32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => number): Float32Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => number, thisArg: undefined): Float32Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => number, thisArg: Z): Float32Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -3675,7 +3810,9 @@ interface Float32Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -3728,7 +3865,11 @@ interface Float32ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Float32Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float32Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Float32Array;
|
||||
|
||||
}
|
||||
declare const Float32Array: Float32ArrayConstructor;
|
||||
@@ -3777,7 +3918,9 @@ interface Float64Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
every(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean): boolean;
|
||||
every(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean, thisArg: undefined): boolean;
|
||||
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
@@ -3796,7 +3939,9 @@ interface Float64Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
filter(callbackfn: (value: number, index: number, array: Float64Array) => any, thisArg?: any): Float64Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => any): Float64Array;
|
||||
filter(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => any, thisArg: undefined): Float64Array;
|
||||
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => any, thisArg: Z): Float64Array;
|
||||
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
@@ -3807,7 +3952,9 @@ interface Float64Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
|
||||
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
|
||||
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and -1
|
||||
@@ -3818,7 +3965,9 @@ interface Float64Array {
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
|
||||
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
|
||||
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
|
||||
|
||||
/**
|
||||
* Performs the specified action for each element in an array.
|
||||
@@ -3827,7 +3976,9 @@ interface Float64Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
forEach(callbackfn: (value: number, index: number, array: Float64Array) => void, thisArg?: any): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => void): void;
|
||||
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => void, thisArg: undefined): void;
|
||||
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => void, thisArg: Z): void;
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of a value in an array.
|
||||
@@ -3865,7 +4016,9 @@ interface Float64Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
map(callbackfn: (value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => number): Float64Array;
|
||||
map(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => number, thisArg: undefined): Float64Array;
|
||||
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => number, thisArg: Z): Float64Array;
|
||||
|
||||
/**
|
||||
* Calls the specified callback function for all the elements in an array. The return value of
|
||||
@@ -3949,7 +4102,9 @@ interface Float64Array {
|
||||
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
||||
* If thisArg is omitted, undefined is used as the this value.
|
||||
*/
|
||||
some(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean): boolean;
|
||||
some(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean, thisArg: undefined): boolean;
|
||||
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => boolean, thisArg: Z): boolean;
|
||||
|
||||
/**
|
||||
* Sorts an array.
|
||||
@@ -4002,7 +4157,11 @@ interface Float64ArrayConstructor {
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Float64Array;
|
||||
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float64Array;
|
||||
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array;
|
||||
|
||||
from(arrayLike: ArrayLike<number>): Float64Array;
|
||||
}
|
||||
declare const Float64Array: Float64ArrayConstructor;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
|
||||
return {
|
||||
isCancellationRequested: () => perRequestPipeName !== undefined && pipeExists(perRequestPipeName),
|
||||
setRequest(requestId: number) {
|
||||
currentRequestId = currentRequestId;
|
||||
currentRequestId = requestId;
|
||||
perRequestPipeName = namePrefix + requestId;
|
||||
},
|
||||
resetRequest(requestId: number) {
|
||||
@@ -67,4 +67,4 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
|
||||
};
|
||||
}
|
||||
}
|
||||
export = createCancellationToken;
|
||||
export = createCancellationToken;
|
||||
|
||||
@@ -2127,6 +2127,17 @@ namespace ts.server.protocol {
|
||||
payload: any;
|
||||
}
|
||||
|
||||
export type TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed";
|
||||
|
||||
export interface TypesInstallerInitializationFailedEvent extends Event {
|
||||
event: TypesInstallerInitializationFailedEventName;
|
||||
body: TypesInstallerInitializationFailedEventBody;
|
||||
}
|
||||
|
||||
export interface TypesInstallerInitializationFailedEventBody {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export type TypingsInstalledTelemetryEventName = "typingsInstalled";
|
||||
|
||||
export interface TypingsInstalledTelemetryEventBody extends TelemetryEventBody {
|
||||
|
||||
+51
-28
@@ -131,6 +131,14 @@ namespace ts.server {
|
||||
constructor(private readonly logFilename: string,
|
||||
private readonly traceToConsole: boolean,
|
||||
private readonly level: LogLevel) {
|
||||
if (this.logFilename) {
|
||||
try {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
}
|
||||
catch(_) {
|
||||
// swallow the error and keep logging disabled if file cannot be opened
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static padStringRight(str: string, padding: string) {
|
||||
@@ -175,11 +183,6 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
msg(s: string, type: Msg.Types = Msg.Err) {
|
||||
if (this.fd < 0) {
|
||||
if (this.logFilename) {
|
||||
this.fd = fs.openSync(this.logFilename, "w");
|
||||
}
|
||||
}
|
||||
if (this.fd >= 0 || this.traceToConsole) {
|
||||
s = s + "\n";
|
||||
const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " ");
|
||||
@@ -301,11 +304,23 @@ namespace ts.server {
|
||||
});
|
||||
}
|
||||
|
||||
private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes) {
|
||||
private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Received response: ${JSON.stringify(response)}`);
|
||||
}
|
||||
|
||||
if (response.kind === EventInitializationFailed) {
|
||||
if (!this.eventSender) {
|
||||
return;
|
||||
}
|
||||
const body: protocol.TypesInstallerInitializationFailedEventBody = {
|
||||
message: response.message
|
||||
}
|
||||
const eventName: protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed";
|
||||
this.eventSender.event(body, eventName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.kind === EventBeginInstallTypes) {
|
||||
if (!this.eventSender) {
|
||||
return;
|
||||
@@ -410,6 +425,9 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
function parseLoggingEnvironmentString(logEnvStr: string): LogOptions {
|
||||
if (!logEnvStr) {
|
||||
return {};
|
||||
}
|
||||
const logEnv: LogOptions = { logToFile: true };
|
||||
const args = logEnvStr.split(" ");
|
||||
const len = args.length - 1;
|
||||
@@ -422,8 +440,8 @@ namespace ts.server {
|
||||
logEnv.file = stripQuotes(value);
|
||||
break;
|
||||
case "-level":
|
||||
const level: LogLevel = (<any>LogLevel)[value];
|
||||
logEnv.detailLevel = typeof level === "number" ? level : LogLevel.normal;
|
||||
const level = getLogLevel(value);
|
||||
logEnv.detailLevel = level !== undefined ? level : LogLevel.normal;
|
||||
break;
|
||||
case "-traceToConsole":
|
||||
logEnv.traceToConsole = value.toLowerCase() === "true";
|
||||
@@ -437,28 +455,32 @@ namespace ts.server {
|
||||
return logEnv;
|
||||
}
|
||||
|
||||
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
|
||||
function createLoggerFromEnv() {
|
||||
let fileName: string = undefined;
|
||||
let detailLevel = LogLevel.normal;
|
||||
let traceToConsole = false;
|
||||
const logEnvStr = process.env["TSS_LOG"];
|
||||
if (logEnvStr) {
|
||||
const logEnv = parseLoggingEnvironmentString(logEnvStr);
|
||||
if (logEnv.logToFile) {
|
||||
if (logEnv.file) {
|
||||
fileName = logEnv.file;
|
||||
}
|
||||
else {
|
||||
fileName = __dirname + "/.log" + process.pid.toString();
|
||||
function getLogLevel(level: string) {
|
||||
if (level) {
|
||||
const l = level.toLowerCase();
|
||||
for (const name in LogLevel) {
|
||||
if (isNaN(+name) && l === name.toLowerCase()) {
|
||||
return <LogLevel><any>LogLevel[name];
|
||||
}
|
||||
}
|
||||
if (logEnv.detailLevel) {
|
||||
detailLevel = logEnv.detailLevel;
|
||||
}
|
||||
traceToConsole = logEnv.traceToConsole;
|
||||
}
|
||||
return new Logger(fileName, traceToConsole, detailLevel);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
|
||||
function createLogger() {
|
||||
const cmdLineLogFileName = findArgument("--logFile");
|
||||
const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity"));
|
||||
const envLogOptions = parseLoggingEnvironmentString(process.env["TSS_LOG"]);
|
||||
|
||||
const logFileName = cmdLineLogFileName
|
||||
? stripQuotes(cmdLineLogFileName)
|
||||
: envLogOptions.logToFile
|
||||
? envLogOptions.file || (__dirname + "/.log" + process.pid.toString())
|
||||
: undefined;
|
||||
|
||||
const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel;
|
||||
return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity)
|
||||
}
|
||||
// This places log file in the directory containing editorServices.js
|
||||
// TODO: check that this location is writable
|
||||
@@ -555,7 +577,6 @@ namespace ts.server {
|
||||
// to increase the chunk size or decrease the interval
|
||||
// time dynamically to match the large reference set?
|
||||
const pollingWatchedFileSet = createPollingWatchedFileSet();
|
||||
const logger = createLoggerFromEnv();
|
||||
|
||||
const pending: Buffer[] = [];
|
||||
let canWrite = true;
|
||||
@@ -607,6 +628,8 @@ namespace ts.server {
|
||||
return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash;
|
||||
}
|
||||
|
||||
const logger = createLogger();
|
||||
|
||||
const sys = <ServerHost>ts.sys;
|
||||
// use watchGuard process on Windows when node version is 4 or later
|
||||
const useWatchGuard = process.platform === "win32" && getNodeMajorVersion() >= 4;
|
||||
|
||||
@@ -1420,8 +1420,9 @@ namespace ts.server {
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
|
||||
const startPosition = getStartPosition();
|
||||
const endPosition = getEndPosition();
|
||||
const formatOptions = this.projectService.getFormatCodeOptions(file);
|
||||
|
||||
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes);
|
||||
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, formatOptions);
|
||||
if (!codeActions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace ts.server {
|
||||
export const ActionInvalidate: ActionInvalidate = "action::invalidate";
|
||||
export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes";
|
||||
export const EventInitializationFailed: EventInitializationFailed = "event::initializationFailed";
|
||||
|
||||
export namespace Arguments {
|
||||
export const GlobalCacheLocation = "--globalTypingsCacheLocation";
|
||||
|
||||
+7
-1
@@ -47,9 +47,15 @@ declare namespace ts.server {
|
||||
export type ActionInvalidate = "action::invalidate";
|
||||
export type EventBeginInstallTypes = "event::beginInstallTypes";
|
||||
export type EventEndInstallTypes = "event::endInstallTypes";
|
||||
export type EventInitializationFailed = "event::initializationFailed";
|
||||
|
||||
export interface TypingInstallerResponse {
|
||||
readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes;
|
||||
readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
|
||||
}
|
||||
|
||||
export interface InitializationFailedResponse extends TypingInstallerResponse {
|
||||
readonly kind: EventInitializationFailed;
|
||||
readonly message: string;
|
||||
}
|
||||
|
||||
export interface ProjectResponse extends TypingInstallerResponse {
|
||||
|
||||
@@ -13,14 +13,20 @@ namespace ts.server.typingsInstaller {
|
||||
} = require("path");
|
||||
|
||||
class FileLog implements Log {
|
||||
private logEnabled = true;
|
||||
constructor(private readonly logFile?: string) {
|
||||
}
|
||||
|
||||
isEnabled() {
|
||||
return this.logFile !== undefined;
|
||||
return this.logEnabled && this.logFile !== undefined;
|
||||
}
|
||||
writeLine(text: string) {
|
||||
fs.appendFileSync(this.logFile, text + sys.newLine);
|
||||
try {
|
||||
fs.appendFileSync(this.logFile, text + sys.newLine);
|
||||
}
|
||||
catch(e) {
|
||||
this.logEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +74,8 @@ namespace ts.server.typingsInstaller {
|
||||
private readonly npmPath: string;
|
||||
readonly typesRegistry: Map<void>;
|
||||
|
||||
private delayedInitializationError: InitializationFailedResponse;
|
||||
|
||||
constructor(globalTypingsCacheLocation: string, throttleLimit: number, log: Log) {
|
||||
super(
|
||||
sys,
|
||||
@@ -93,6 +101,11 @@ namespace ts.server.typingsInstaller {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Error updating ${TypesRegistryPackageName} package: ${(<Error>e).message}`);
|
||||
}
|
||||
// store error info to report it later when it is known that server is already listening to events from typings installer
|
||||
this.delayedInitializationError = {
|
||||
kind: "event::initializationFailed",
|
||||
message: (<Error>e).message
|
||||
};
|
||||
}
|
||||
|
||||
this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), this.installTypingHost, this.log);
|
||||
@@ -100,6 +113,11 @@ namespace ts.server.typingsInstaller {
|
||||
|
||||
listen() {
|
||||
process.on("message", (req: DiscoverTypings | CloseProject) => {
|
||||
if (this.delayedInitializationError) {
|
||||
// report initializationFailed error
|
||||
this.sendResponse(this.delayedInitializationError);
|
||||
this.delayedInitializationError = undefined;
|
||||
}
|
||||
switch (req.kind) {
|
||||
case "discover":
|
||||
this.install(req);
|
||||
@@ -110,7 +128,7 @@ namespace ts.server.typingsInstaller {
|
||||
});
|
||||
}
|
||||
|
||||
protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes) {
|
||||
protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Sending response: ${JSON.stringify(response)}`);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ts {
|
||||
newLineCharacter: string;
|
||||
host: LanguageServiceHost;
|
||||
cancellationToken: CancellationToken;
|
||||
rulesProvider: formatting.RulesProvider;
|
||||
}
|
||||
|
||||
export namespace codefix {
|
||||
|
||||
@@ -26,22 +26,13 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newPosition = getOpenBraceEnd(<ConstructorDeclaration>constructor, sourceFile);
|
||||
const changes = [{
|
||||
fileName: sourceFile.fileName, textChanges: [{
|
||||
newText: superCall.getText(sourceFile),
|
||||
span: { start: newPosition, length: 0 }
|
||||
},
|
||||
{
|
||||
newText: "",
|
||||
span: { start: superCall.getStart(sourceFile), length: superCall.getWidth(sourceFile) }
|
||||
}]
|
||||
}];
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.insertNodeAfter(sourceFile, getOpenBrace(<ConstructorDeclaration>constructor, sourceFile), superCall, { suffix: context.newLineCharacter });
|
||||
changeTracker.deleteNode(sourceFile, superCall);
|
||||
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Make_super_call_the_first_statement_in_the_constructor),
|
||||
changes
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
|
||||
function findSuperCall(n: Node): ExpressionStatement {
|
||||
|
||||
@@ -10,10 +10,13 @@ namespace ts.codefix {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const newPosition = getOpenBraceEnd(<ConstructorDeclaration>token.parent, sourceFile);
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
const superCall = createStatement(createCall(createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray));
|
||||
changeTracker.insertNodeAfter(sourceFile, getOpenBrace(<ConstructorDeclaration>token.parent, sourceFile), superCall, { suffix: context.newLineCharacter });
|
||||
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Add_missing_super_call),
|
||||
changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "super();", span: { start: newPosition, length: 0 } }] }]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -21,26 +21,20 @@ namespace ts.codefix {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let changeStart = extendsToken.getStart(sourceFile);
|
||||
let changeEnd = extendsToken.getEnd();
|
||||
const textChanges: TextChange[] = [{ newText: " implements", span: { start: changeStart, length: changeEnd - changeStart } }];
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.replaceNode(sourceFile, extendsToken, createToken(SyntaxKind.ImplementsKeyword));
|
||||
|
||||
// We replace existing keywords with commas.
|
||||
for (let i = 1; i < heritageClauses.length; i++) {
|
||||
const keywordToken = heritageClauses[i].getFirstToken();
|
||||
if (keywordToken) {
|
||||
changeStart = keywordToken.getStart(sourceFile);
|
||||
changeEnd = keywordToken.getEnd();
|
||||
textChanges.push({ newText: ",", span: { start: changeStart, length: changeEnd - changeStart } });
|
||||
changeTracker.replaceNode(sourceFile, keywordToken, createToken(SyntaxKind.CommaToken));
|
||||
}
|
||||
}
|
||||
|
||||
const result = [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Change_extends_to_implements),
|
||||
changes: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textChanges: textChanges
|
||||
}]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
|
||||
return result;
|
||||
|
||||
@@ -5,11 +5,15 @@ namespace ts.codefix {
|
||||
getCodeActions: (context: CodeFixContext) => {
|
||||
const sourceFile = context.sourceFile;
|
||||
const token = getTokenAtPosition(sourceFile, context.span.start);
|
||||
const start = token.getStart(sourceFile);
|
||||
if (token.kind !== SyntaxKind.Identifier) {
|
||||
return undefined;
|
||||
}
|
||||
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.replaceNode(sourceFile, token, createPropertyAccess(createThis(), <Identifier>token));
|
||||
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Add_this_to_unresolved_variable),
|
||||
changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "this.", span: { start, length: 0 } }] }]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace ts.codefix {
|
||||
|
||||
// this is a module id -> module import declaration map
|
||||
const cachedImportDeclarations: (ImportDeclaration | ImportEqualsDeclaration)[][] = [];
|
||||
let cachedNewImportInsertPosition: number;
|
||||
let lastImportDeclaration: Node;
|
||||
|
||||
const currentTokenMeaning = getMeaningFromLocation(token);
|
||||
if (context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
|
||||
@@ -138,14 +138,14 @@ namespace ts.codefix {
|
||||
return getCodeActionForImport(symbol, /*isDefault*/ false, /*isNamespaceImport*/ true);
|
||||
}
|
||||
|
||||
const allPotentialModules = checker.getAmbientModules();
|
||||
const candidateModules = checker.getAmbientModules();
|
||||
for (const otherSourceFile of allSourceFiles) {
|
||||
if (otherSourceFile !== sourceFile && isExternalOrCommonJsModule(otherSourceFile)) {
|
||||
allPotentialModules.push(otherSourceFile.symbol);
|
||||
candidateModules.push(otherSourceFile.symbol);
|
||||
}
|
||||
}
|
||||
|
||||
for (const moduleSymbol of allPotentialModules) {
|
||||
for (const moduleSymbol of candidateModules) {
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
// check the default export
|
||||
@@ -277,14 +277,12 @@ namespace ts.codefix {
|
||||
* If the existing import declaration already has a named import list, just
|
||||
* insert the identifier into that list.
|
||||
*/
|
||||
const textChange = getTextChangeForImportClause(namedImportDeclaration.importClause);
|
||||
const fileTextChanges = getTextChangeForImportClause(namedImportDeclaration.importClause);
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(namedImportDeclaration.moduleSpecifier.getText());
|
||||
actions.push(createCodeAction(
|
||||
Diagnostics.Add_0_to_existing_import_declaration_from_1,
|
||||
[name, moduleSpecifierWithoutQuotes],
|
||||
textChange.newText,
|
||||
textChange.span,
|
||||
sourceFile.fileName,
|
||||
fileTextChanges,
|
||||
"InsertingIntoExistingImport",
|
||||
moduleSpecifierWithoutQuotes
|
||||
));
|
||||
@@ -302,49 +300,31 @@ namespace ts.codefix {
|
||||
return declaration.moduleReference.getText();
|
||||
}
|
||||
|
||||
function getTextChangeForImportClause(importClause: ImportClause): TextChange {
|
||||
const newImportText = isDefault ? `default as ${name}` : name;
|
||||
function getTextChangeForImportClause(importClause: ImportClause): FileTextChanges[] {
|
||||
//const newImportText = isDefault ? `default as ${name}` : name;
|
||||
const importList = <NamedImports>importClause.namedBindings;
|
||||
const newImportSpecifier = createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name));
|
||||
// case 1:
|
||||
// original text: import default from "module"
|
||||
// change to: import default, { name } from "module"
|
||||
if (!importList && importClause.name) {
|
||||
const start = importClause.name.getEnd();
|
||||
return {
|
||||
newText: `, { ${newImportText} }`,
|
||||
span: { start, length: 0 }
|
||||
};
|
||||
}
|
||||
|
||||
// case 2:
|
||||
// original text: import {} from "module"
|
||||
// change to: import { name } from "module"
|
||||
if (importList.elements.length === 0) {
|
||||
const start = importList.getStart();
|
||||
return {
|
||||
newText: `{ ${newImportText} }`,
|
||||
span: { start, length: importList.getEnd() - start }
|
||||
};
|
||||
if (!importList || importList.elements.length === 0) {
|
||||
const newImportClause = createImportClause(importClause.name, createNamedImports([newImportSpecifier]));
|
||||
return createChangeTracker().replaceNode(sourceFile, importClause, newImportClause).getChanges();
|
||||
}
|
||||
|
||||
// case 3:
|
||||
// original text: import { foo, bar } from "module"
|
||||
// change to: import { foo, bar, name } from "module"
|
||||
const insertPoint = importList.elements[importList.elements.length - 1].getEnd();
|
||||
/**
|
||||
* If the import list has one import per line, preserve that. Otherwise, insert on same line as last element
|
||||
* import {
|
||||
* foo
|
||||
* } from "./module";
|
||||
*/
|
||||
const startLine = getLineOfLocalPosition(sourceFile, importList.getStart());
|
||||
const endLine = getLineOfLocalPosition(sourceFile, importList.getEnd());
|
||||
const oneImportPerLine = endLine - startLine > importList.elements.length;
|
||||
|
||||
return {
|
||||
newText: `,${oneImportPerLine ? context.newLineCharacter : " "}${newImportText}`,
|
||||
span: { start: insertPoint, length: 0 }
|
||||
};
|
||||
return createChangeTracker().insertNodeInListAfter(
|
||||
sourceFile,
|
||||
importList.elements[importList.elements.length - 1],
|
||||
newImportSpecifier).getChanges();
|
||||
}
|
||||
|
||||
function getCodeActionForNamespaceImport(declaration: ImportDeclaration | ImportEqualsDeclaration): ImportCodeAction {
|
||||
@@ -370,48 +350,47 @@ namespace ts.codefix {
|
||||
return createCodeAction(
|
||||
Diagnostics.Change_0_to_1,
|
||||
[name, `${namespacePrefix}.${name}`],
|
||||
`${namespacePrefix}.`,
|
||||
{ start: token.getStart(), length: 0 },
|
||||
sourceFile.fileName,
|
||||
createChangeTracker().replaceNode(sourceFile, token, createPropertyAccess(createIdentifier(namespacePrefix), name)).getChanges(),
|
||||
"CodeChange"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getCodeActionForNewImport(moduleSpecifier?: string): ImportCodeAction {
|
||||
if (!cachedNewImportInsertPosition) {
|
||||
if (!lastImportDeclaration) {
|
||||
// insert after any existing imports
|
||||
let lastModuleSpecifierEnd = -1;
|
||||
for (const moduleSpecifier of sourceFile.imports) {
|
||||
const end = moduleSpecifier.getEnd();
|
||||
if (!lastModuleSpecifierEnd || end > lastModuleSpecifierEnd) {
|
||||
lastModuleSpecifierEnd = end;
|
||||
for (let i = sourceFile.statements.length - 1; i >= 0; i--) {
|
||||
const statement = sourceFile.statements[i];
|
||||
if (statement.kind === SyntaxKind.ImportEqualsDeclaration || statement.kind === SyntaxKind.ImportDeclaration) {
|
||||
lastImportDeclaration = statement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cachedNewImportInsertPosition = lastModuleSpecifierEnd > 0 ? sourceFile.getLineEndOfPosition(lastModuleSpecifierEnd) : sourceFile.getStart();
|
||||
}
|
||||
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier || getModuleSpecifierForNewImport());
|
||||
const importStatementText = isDefault
|
||||
? `import ${name} from "${moduleSpecifierWithoutQuotes}"`
|
||||
const changeTracker = createChangeTracker();
|
||||
const importClause = isDefault
|
||||
? createImportClause(createIdentifier(name), /*namedBindings*/ undefined)
|
||||
: isNamespaceImport
|
||||
? `import * as ${name} from "${moduleSpecifierWithoutQuotes}"`
|
||||
: `import { ${name} } from "${moduleSpecifierWithoutQuotes}"`;
|
||||
? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(name)))
|
||||
: createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))]));
|
||||
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, createLiteral(moduleSpecifierWithoutQuotes));
|
||||
if (!lastImportDeclaration) {
|
||||
changeTracker.insertNodeAt(sourceFile, sourceFile.getStart(), importDecl, { suffix: `${context.newLineCharacter}${context.newLineCharacter}` });
|
||||
}
|
||||
else {
|
||||
changeTracker.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl, { suffix: context.newLineCharacter });
|
||||
}
|
||||
|
||||
// if this file doesn't have any import statements, insert an import statement and then insert a new line
|
||||
// between the only import statement and user code. Otherwise just insert the statement because chances
|
||||
// are there are already a new line seperating code and import statements.
|
||||
const newText = cachedNewImportInsertPosition === sourceFile.getStart()
|
||||
? `${importStatementText};${context.newLineCharacter}${context.newLineCharacter}`
|
||||
: `${context.newLineCharacter}${importStatementText};`;
|
||||
|
||||
return createCodeAction(
|
||||
Diagnostics.Import_0_from_1,
|
||||
[name, `"${moduleSpecifierWithoutQuotes}"`],
|
||||
newText,
|
||||
{ start: cachedNewImportInsertPosition, length: 0 },
|
||||
sourceFile.fileName,
|
||||
changeTracker.getChanges(),
|
||||
"NewImport",
|
||||
moduleSpecifierWithoutQuotes
|
||||
);
|
||||
@@ -576,17 +555,19 @@ namespace ts.codefix {
|
||||
|
||||
}
|
||||
|
||||
function createChangeTracker() {
|
||||
return textChanges.ChangeTracker.fromCodeFixContext(context);;
|
||||
}
|
||||
|
||||
function createCodeAction(
|
||||
description: DiagnosticMessage,
|
||||
diagnosticArgs: string[],
|
||||
newText: string,
|
||||
span: TextSpan,
|
||||
fileName: string,
|
||||
changes: FileTextChanges[],
|
||||
kind: ImportCodeActionKind,
|
||||
moduleSpecifier?: string): ImportCodeAction {
|
||||
return {
|
||||
description: formatMessage.apply(undefined, [undefined, description].concat(<any[]>diagnosticArgs)),
|
||||
changes: [{ fileName, textChanges: [{ newText, span }] }],
|
||||
changes,
|
||||
kind,
|
||||
moduleSpecifier
|
||||
};
|
||||
|
||||
@@ -25,17 +25,17 @@ namespace ts.codefix {
|
||||
const forStatement = <ForStatement>token.parent.parent.parent;
|
||||
const forInitializer = <VariableDeclarationList>forStatement.initializer;
|
||||
if (forInitializer.declarations.length === 1) {
|
||||
return createCodeFixToRemoveNode(forInitializer);
|
||||
return deleteNode(forInitializer);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(forInitializer.declarations, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
const forOfStatement = <ForOfStatement>token.parent.parent.parent;
|
||||
if (forOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
|
||||
const forOfInitializer = <VariableDeclarationList>forOfStatement.initializer;
|
||||
return createCodeFix("{}", forOfInitializer.declarations[0].getStart(), forOfInitializer.declarations[0].getWidth());
|
||||
return replaceNode(forOfInitializer.declarations[0], createObjectLiteral());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -47,51 +47,59 @@ namespace ts.codefix {
|
||||
case SyntaxKind.CatchClause:
|
||||
const catchClause = <CatchClause>token.parent.parent;
|
||||
const parameter = catchClause.variableDeclaration.getChildren()[0];
|
||||
return createCodeFixToRemoveNode(parameter);
|
||||
return deleteNode(parameter);
|
||||
|
||||
default:
|
||||
const variableStatement = <VariableStatement>token.parent.parent.parent;
|
||||
if (variableStatement.declarationList.declarations.length === 1) {
|
||||
return createCodeFixToRemoveNode(variableStatement);
|
||||
return deleteNode(variableStatement);
|
||||
}
|
||||
else {
|
||||
const declarations = variableStatement.declarationList.declarations;
|
||||
return removeSingleItem(declarations, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
}
|
||||
|
||||
case SyntaxKind.TypeParameter:
|
||||
const typeParameters = (<DeclarationWithTypeParameters>token.parent.parent).typeParameters;
|
||||
if (typeParameters.length === 1) {
|
||||
return createCodeFix("", token.parent.pos - 1, token.parent.end - token.parent.pos + 2);
|
||||
const previousToken = getTokenAtPosition(sourceFile, typeParameters.pos - 1);
|
||||
if (!previousToken || previousToken.kind !== SyntaxKind.LessThanToken) {
|
||||
return deleteRange(typeParameters);
|
||||
}
|
||||
const nextToken = getTokenAtPosition(sourceFile, typeParameters.end);
|
||||
if (!nextToken || nextToken.kind !== SyntaxKind.GreaterThanToken) {
|
||||
return deleteRange(typeParameters);
|
||||
}
|
||||
return deleteNodeRange(previousToken, nextToken);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(typeParameters, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
case ts.SyntaxKind.Parameter:
|
||||
const functionDeclaration = <FunctionDeclaration>token.parent.parent;
|
||||
if (functionDeclaration.parameters.length === 1) {
|
||||
return createCodeFixToRemoveNode(token.parent);
|
||||
return deleteNode(token.parent);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(functionDeclaration.parameters, token);
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
// handle case where 'import a = A;'
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
const importEquals = findImportDeclaration(token);
|
||||
return createCodeFixToRemoveNode(importEquals);
|
||||
const importEquals = getAncestor(token, SyntaxKind.ImportEqualsDeclaration);
|
||||
return deleteNode(importEquals);
|
||||
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
const namedImports = <NamedImports>token.parent.parent;
|
||||
if (namedImports.elements.length === 1) {
|
||||
// Only 1 import and it is unused. So the entire declaration should be removed.
|
||||
const importSpec = findImportDeclaration(token);
|
||||
return createCodeFixToRemoveNode(importSpec);
|
||||
const importSpec = getAncestor(token, SyntaxKind.ImportDeclaration);
|
||||
return deleteNode(importSpec);
|
||||
}
|
||||
else {
|
||||
return removeSingleItem(namedImports.elements, token);
|
||||
// delete import specifier
|
||||
return deleteNodeInList(token.parent);
|
||||
}
|
||||
|
||||
// handle case where "import d, * as ns from './file'"
|
||||
@@ -99,92 +107,79 @@ namespace ts.codefix {
|
||||
case SyntaxKind.ImportClause: // this covers both 'import |d|' and 'import |d,| *'
|
||||
const importClause = <ImportClause>token.parent;
|
||||
if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'|
|
||||
const importDecl = findImportDeclaration(importClause);
|
||||
return createCodeFixToRemoveNode(importDecl);
|
||||
const importDecl = getAncestor(importClause, SyntaxKind.ImportDeclaration);
|
||||
return deleteNode(importDecl);
|
||||
}
|
||||
else {
|
||||
// import |d,| * as ns from './file'
|
||||
const start = importClause.name.getStart();
|
||||
const text = sourceFile.text;
|
||||
let end = getFirstNonSpaceCharacterPosition(text, importClause.name.end);
|
||||
if (sourceFile.text.charCodeAt(end) === CharacterCodes.comma) {
|
||||
end = getFirstNonSpaceCharacterPosition(text, end + 1);
|
||||
const start = importClause.name.getStart(sourceFile);
|
||||
const nextToken = getTokenAtPosition(sourceFile, importClause.name.end);
|
||||
if (nextToken && nextToken.kind === SyntaxKind.CommaToken) {
|
||||
// shift first non-whitespace position after comma to the start position of the node
|
||||
return deleteRange({ pos: start, end: skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/true) });
|
||||
}
|
||||
else {
|
||||
return deleteNode(importClause.name);
|
||||
}
|
||||
|
||||
return createCodeFix("", start, end - start);
|
||||
}
|
||||
|
||||
case SyntaxKind.NamespaceImport:
|
||||
const namespaceImport = <NamespaceImport>token.parent;
|
||||
if (namespaceImport.name == token && !(<ImportClause>namespaceImport.parent).name) {
|
||||
const importDecl = findImportDeclaration(namespaceImport);
|
||||
return createCodeFixToRemoveNode(importDecl);
|
||||
const importDecl = getAncestor(namespaceImport, SyntaxKind.ImportDeclaration);
|
||||
return deleteNode(importDecl);
|
||||
}
|
||||
else {
|
||||
const start = (<ImportClause>namespaceImport.parent).name.end;
|
||||
return createCodeFix("", start, (<ImportClause>namespaceImport.parent).namedBindings.end - start);
|
||||
const previousToken = getTokenAtPosition(sourceFile, namespaceImport.pos - 1);
|
||||
if (previousToken && previousToken.kind === SyntaxKind.CommaToken) {
|
||||
const startPosition = textChanges.getAdjustedStartPosition(sourceFile, previousToken, {}, textChanges.Position.FullStart);
|
||||
return deleteRange({ pos: startPosition, end: namespaceImport.end });
|
||||
}
|
||||
return deleteRange(namespaceImport);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
return createCodeFixToRemoveNode(token.parent);
|
||||
return deleteNode(token.parent);
|
||||
}
|
||||
if (isDeclarationName(token)) {
|
||||
return createCodeFixToRemoveNode(token.parent);
|
||||
return deleteNode(token.parent);
|
||||
}
|
||||
else if (isLiteralComputedPropertyDeclarationName(token)) {
|
||||
return createCodeFixToRemoveNode(token.parent.parent);
|
||||
return deleteNode(token.parent.parent);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function findImportDeclaration(token: Node): Node {
|
||||
let importDecl = token;
|
||||
while (importDecl.kind != SyntaxKind.ImportDeclaration && importDecl.parent) {
|
||||
importDecl = importDecl.parent;
|
||||
}
|
||||
|
||||
return importDecl;
|
||||
function deleteNode(n: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNode(sourceFile, n));
|
||||
}
|
||||
|
||||
function createCodeFixToRemoveNode(node: Node) {
|
||||
let end = node.getEnd();
|
||||
const endCharCode = sourceFile.text.charCodeAt(end);
|
||||
const afterEndCharCode = sourceFile.text.charCodeAt(end + 1);
|
||||
if (isLineBreak(endCharCode)) {
|
||||
end += 1;
|
||||
}
|
||||
// in the case of CR LF, you could have two consecutive new line characters for one new line.
|
||||
// this needs to be differenciated from two LF LF chars that actually mean two new lines.
|
||||
if (isLineBreak(afterEndCharCode) && endCharCode !== afterEndCharCode) {
|
||||
end += 1;
|
||||
}
|
||||
|
||||
const start = node.getStart();
|
||||
return createCodeFix("", start, end - start);
|
||||
function deleteRange(range: TextRange) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteRange(sourceFile, range));
|
||||
}
|
||||
|
||||
function createCodeFix(newText: string, start: number, length: number): CodeAction[] {
|
||||
function deleteNodeInList(n: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNodeInList(sourceFile, n));
|
||||
}
|
||||
|
||||
function deleteNodeRange(start: Node, end: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNodeRange(sourceFile, start, end));
|
||||
}
|
||||
|
||||
function replaceNode(n: Node, newNode: Node) {
|
||||
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).replaceNode(sourceFile, n, newNode));
|
||||
}
|
||||
|
||||
function makeChange(changeTracker: textChanges.ChangeTracker) {
|
||||
return [{
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }),
|
||||
changes: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textChanges: [{ newText, span: { start, length } }]
|
||||
}]
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
}
|
||||
|
||||
function removeSingleItem<T extends Node>(elements: NodeArray<T>, token: T): CodeAction[] {
|
||||
if (elements[0] === token.parent) {
|
||||
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos + 1);
|
||||
}
|
||||
else {
|
||||
return createCodeFix("", token.parent.pos - 1, token.parent.end - token.parent.pos + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -447,8 +447,8 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { parent, kind } = contextToken;
|
||||
if (kind === SyntaxKind.DotToken) {
|
||||
let parent = contextToken.parent;
|
||||
if (contextToken.kind === SyntaxKind.DotToken) {
|
||||
if (parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
node = (<PropertyAccessExpression>contextToken.parent).expression;
|
||||
isRightOfDot = true;
|
||||
@@ -464,16 +464,24 @@ namespace ts.Completions {
|
||||
}
|
||||
}
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
switch (contextToken.parent.kind) {
|
||||
// <UI.Test /* completion position */ />
|
||||
// If the tagname is a property access expression, we will then walk up to the top most of property access expression.
|
||||
// Then, try to get a JSX container and its associated attributes type.
|
||||
if (parent && parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
contextToken = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
if (kind === SyntaxKind.SlashToken) {
|
||||
if (contextToken.kind === SyntaxKind.SlashToken) {
|
||||
isStartingCloseTag = true;
|
||||
location = contextToken;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (!((contextToken.parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) {
|
||||
if (!((parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) {
|
||||
// It has a left-hand side, so we're not in an opening JSX tag.
|
||||
break;
|
||||
}
|
||||
@@ -482,7 +490,7 @@ namespace ts.Completions {
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxElement:
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
if (kind === SyntaxKind.LessThanToken) {
|
||||
if (contextToken.kind === SyntaxKind.LessThanToken) {
|
||||
isRightOfOpenTag = true;
|
||||
location = contextToken;
|
||||
}
|
||||
@@ -950,6 +958,7 @@ namespace ts.Completions {
|
||||
case SyntaxKind.LessThanSlashToken:
|
||||
case SyntaxKind.SlashToken:
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
case SyntaxKind.JsxAttribute:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
|
||||
@@ -314,24 +314,55 @@ namespace ts.formatting {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function formatNode(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, rulesProvider: RulesProvider): TextChange[] {
|
||||
const range = { pos: 0, end: sourceFileLike.text.length };
|
||||
return formatSpanWorker(
|
||||
range,
|
||||
node,
|
||||
initialIndentation,
|
||||
delta,
|
||||
getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end),
|
||||
rulesProvider.getFormatOptions(),
|
||||
rulesProvider,
|
||||
FormattingRequestKind.FormatSelection,
|
||||
_ => false, // assume that node does not have any errors
|
||||
sourceFileLike);
|
||||
}
|
||||
|
||||
function formatSpan(originalRange: TextRange,
|
||||
sourceFile: SourceFile,
|
||||
options: FormatCodeSettings,
|
||||
rulesProvider: RulesProvider,
|
||||
requestKind: FormattingRequestKind): TextChange[] {
|
||||
// find the smallest node that fully wraps the range and compute the initial indentation for the node
|
||||
const enclosingNode = findEnclosingNode(originalRange, sourceFile);
|
||||
return formatSpanWorker(
|
||||
originalRange,
|
||||
enclosingNode,
|
||||
SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options),
|
||||
getOwnOrInheritedDelta(enclosingNode, options, sourceFile),
|
||||
getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end),
|
||||
options,
|
||||
rulesProvider,
|
||||
requestKind,
|
||||
prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange),
|
||||
sourceFile);
|
||||
}
|
||||
|
||||
const rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
|
||||
function formatSpanWorker(originalRange: TextRange,
|
||||
enclosingNode: Node,
|
||||
initialIndentation: number,
|
||||
delta: number,
|
||||
formattingScanner: FormattingScanner,
|
||||
options: FormatCodeSettings,
|
||||
rulesProvider: RulesProvider,
|
||||
requestKind: FormattingRequestKind,
|
||||
rangeContainsError: (r: TextRange) => boolean,
|
||||
sourceFile: SourceFileLike): TextChange[] {
|
||||
|
||||
// formatting context is used by rules provider
|
||||
const formattingContext = new FormattingContext(sourceFile, requestKind);
|
||||
|
||||
// find the smallest node that fully wraps the range and compute the initial indentation for the node
|
||||
const enclosingNode = findEnclosingNode(originalRange, sourceFile);
|
||||
|
||||
const formattingScanner = getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
|
||||
|
||||
const initialIndentation = SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
|
||||
|
||||
let previousRangeHasError: boolean;
|
||||
let previousRange: TextRangeWithKind;
|
||||
let previousParent: Node;
|
||||
@@ -351,7 +382,6 @@ namespace ts.formatting {
|
||||
undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
|
||||
}
|
||||
|
||||
const delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
|
||||
processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ts.formatting {
|
||||
private contextNodeBlockIsOnOneLine: boolean;
|
||||
private nextNodeBlockIsOnOneLine: boolean;
|
||||
|
||||
constructor(public sourceFile: SourceFile, public formattingRequestKind: FormattingRequestKind) {
|
||||
constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind) {
|
||||
}
|
||||
|
||||
public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) {
|
||||
|
||||
@@ -30,11 +30,11 @@ namespace ts.formatting {
|
||||
RescanJsxText,
|
||||
}
|
||||
|
||||
export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
|
||||
export function getFormattingScanner(text: string, languageVariant: LanguageVariant, startPos: number, endPos: number): FormattingScanner {
|
||||
Debug.assert(scanner === undefined, "Scanner should be undefined");
|
||||
scanner = sourceFile.languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
|
||||
scanner = languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
|
||||
|
||||
scanner.setText(sourceFile.text);
|
||||
scanner.setText(text);
|
||||
scanner.setTextPos(startPos);
|
||||
|
||||
let wasNewLine = true;
|
||||
@@ -276,8 +276,8 @@ namespace ts.formatting {
|
||||
function isOnToken(): boolean {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
const current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
|
||||
const startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
|
||||
const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
|
||||
const startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
|
||||
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ namespace ts.formatting {
|
||||
return this.rulesMap;
|
||||
}
|
||||
|
||||
public getFormatOptions(): Readonly<ts.FormatCodeSettings> {
|
||||
return this.options;
|
||||
}
|
||||
|
||||
public ensureUpToDate(options: ts.FormatCodeSettings) {
|
||||
if (!this.options || !ts.compareDataObjects(this.options, options)) {
|
||||
const activeRules = this.createActiveRules(options);
|
||||
|
||||
@@ -8,7 +8,19 @@ namespace ts.formatting {
|
||||
Unknown = -1
|
||||
}
|
||||
|
||||
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings): number {
|
||||
/**
|
||||
* Computed indentation for a given position in source file
|
||||
* @param position - position in file
|
||||
* @param sourceFile - target source file
|
||||
* @param options - set of editor options that control indentation
|
||||
* @param assumeNewLineBeforeCloseBrace - false when getIndentation is called on the text from the real source file.
|
||||
* true - when we need to assume that position is on the newline. This is usefult for codefixes, i.e.
|
||||
* function f() {
|
||||
* |}
|
||||
* when inserting some text after open brace we would like to get the value of indentation as if newline was already there.
|
||||
* However by default indentation at position | will be 0 so 'assumeNewLineBeforeCloseBrace' allows to override this behavior,
|
||||
*/
|
||||
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number {
|
||||
if (position > sourceFile.text.length) {
|
||||
return getBaseIndentation(options); // past EOF
|
||||
}
|
||||
@@ -71,13 +83,14 @@ namespace ts.formatting {
|
||||
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) {
|
||||
currentStart = getStartLineAndCharacterForNode(current, sourceFile);
|
||||
|
||||
if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
|
||||
indentationDelta = 0;
|
||||
const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile);
|
||||
if (nextTokenKind !== NextTokenKind.Unknown) {
|
||||
// handle cases when codefix is about to be inserted before the close brace
|
||||
indentationDelta = assumeNewLineBeforeCloseBrace && nextTokenKind === NextTokenKind.CloseBrace ? options.indentSize : 0;
|
||||
}
|
||||
else {
|
||||
indentationDelta = lineAtPosition !== currentStart.line ? options.indentSize : 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,15 +231,21 @@ namespace ts.formatting {
|
||||
return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
|
||||
}
|
||||
|
||||
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): boolean {
|
||||
const enum NextTokenKind {
|
||||
Unknown,
|
||||
OpenBrace,
|
||||
CloseBrace
|
||||
}
|
||||
|
||||
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): NextTokenKind {
|
||||
const nextToken = findNextToken(precedingToken, current);
|
||||
if (!nextToken) {
|
||||
return false;
|
||||
return NextTokenKind.Unknown;
|
||||
}
|
||||
|
||||
if (nextToken.kind === SyntaxKind.OpenBraceToken) {
|
||||
// open braces are always indented at the parent level
|
||||
return true;
|
||||
return NextTokenKind.OpenBrace;
|
||||
}
|
||||
else if (nextToken.kind === SyntaxKind.CloseBraceToken) {
|
||||
// close braces are indented at the parent level if they are located on the same line with cursor
|
||||
@@ -239,17 +258,17 @@ namespace ts.formatting {
|
||||
// $}
|
||||
|
||||
const nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
|
||||
return lineAtPosition === nextTokenStartLine;
|
||||
return lineAtPosition === nextTokenStartLine ? NextTokenKind.CloseBrace : NextTokenKind.Unknown;
|
||||
}
|
||||
|
||||
return false;
|
||||
return NextTokenKind.Unknown;
|
||||
}
|
||||
|
||||
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
|
||||
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFileLike): LineAndCharacter {
|
||||
return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
|
||||
}
|
||||
|
||||
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
|
||||
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean {
|
||||
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
|
||||
const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
|
||||
Debug.assert(elseKeyword !== undefined);
|
||||
@@ -261,15 +280,15 @@ namespace ts.formatting {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
|
||||
function getListIfStartEndIsInListRange(list: NodeArray<Node>, start: number, end: number) {
|
||||
return list && rangeContainsStartEnd(list, start, end) ? list : undefined;
|
||||
}
|
||||
|
||||
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
|
||||
if (node.parent) {
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
if ((<TypeReferenceNode>node.parent).typeArguments &&
|
||||
rangeContainsStartEnd((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd())) {
|
||||
return (<TypeReferenceNode>node.parent).typeArguments;
|
||||
}
|
||||
break;
|
||||
return getListIfStartEndIsInListRange((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd());
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return (<ObjectLiteralExpression>node.parent).properties;
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
@@ -280,30 +299,26 @@ namespace ts.formatting {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.ConstructSignature: {
|
||||
const start = node.getStart(sourceFile);
|
||||
if ((<SignatureDeclaration>node.parent).typeParameters &&
|
||||
rangeContainsStartEnd((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd())) {
|
||||
return (<SignatureDeclaration>node.parent).typeParameters;
|
||||
}
|
||||
if (rangeContainsStartEnd((<SignatureDeclaration>node.parent).parameters, start, node.getEnd())) {
|
||||
return (<SignatureDeclaration>node.parent).parameters;
|
||||
}
|
||||
break;
|
||||
return getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd()) ||
|
||||
getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).parameters, start, node.getEnd());
|
||||
}
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return getListIfStartEndIsInListRange((<ClassDeclaration>node.parent).typeParameters, node.getStart(sourceFile), node.getEnd());
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.CallExpression: {
|
||||
const start = node.getStart(sourceFile);
|
||||
if ((<CallExpression>node.parent).typeArguments &&
|
||||
rangeContainsStartEnd((<CallExpression>node.parent).typeArguments, start, node.getEnd())) {
|
||||
return (<CallExpression>node.parent).typeArguments;
|
||||
}
|
||||
if ((<CallExpression>node.parent).arguments &&
|
||||
rangeContainsStartEnd((<CallExpression>node.parent).arguments, start, node.getEnd())) {
|
||||
return (<CallExpression>node.parent).arguments;
|
||||
}
|
||||
break;
|
||||
return getListIfStartEndIsInListRange((<CallExpression>node.parent).typeArguments, start, node.getEnd()) ||
|
||||
getListIfStartEndIsInListRange((<CallExpression>node.parent).arguments, start, node.getEnd());
|
||||
}
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
return getListIfStartEndIsInListRange((<VariableDeclarationList>node.parent).declarations, node.getStart(sourceFile), node.getEnd());
|
||||
case SyntaxKind.NamedImports:
|
||||
case SyntaxKind.NamedExports:
|
||||
return getListIfStartEndIsInListRange((<NamedImportsOrExports>node.parent).elements, node.getStart(sourceFile), node.getEnd());
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@@ -400,7 +415,7 @@ namespace ts.formatting {
|
||||
value of 'character' for '$' is 3
|
||||
value of 'column' for '$' is 6 (assuming that tab size is 4)
|
||||
*/
|
||||
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings) {
|
||||
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings) {
|
||||
let character = 0;
|
||||
let column = 0;
|
||||
for (let pos = startPos; pos < endPos; pos++) {
|
||||
@@ -421,7 +436,7 @@ namespace ts.formatting {
|
||||
return { column, character };
|
||||
}
|
||||
|
||||
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): number {
|
||||
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings): number {
|
||||
return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +178,8 @@ namespace ts.JsDoc {
|
||||
const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position);
|
||||
const lineStart = sourceFile.getLineStarts()[posLineAndChar.line];
|
||||
|
||||
const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character);
|
||||
// replace non-whitespace characters in prefix with spaces.
|
||||
const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).replace(/\S/i, () => " ");
|
||||
const isJavaScriptFile = hasJavaScriptFileExtension(sourceFile.fileName);
|
||||
|
||||
let docParams = "";
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/// <reference path='transpile.ts' />
|
||||
/// <reference path='formatting\formatting.ts' />
|
||||
/// <reference path='formatting\smartIndenter.ts' />
|
||||
/// <reference path='textChanges.ts' />
|
||||
/// <reference path='codeFixProvider.ts' />
|
||||
/// <reference path='codefixes\fixes.ts' />
|
||||
|
||||
@@ -63,7 +64,7 @@ namespace ts {
|
||||
return getSourceFileOfNode(this);
|
||||
}
|
||||
|
||||
public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
|
||||
public getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number {
|
||||
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ namespace ts {
|
||||
return list;
|
||||
}
|
||||
|
||||
private createChildren(sourceFile?: SourceFile) {
|
||||
private createChildren(sourceFile?: SourceFileLike) {
|
||||
let children: Node[];
|
||||
if (this.kind >= SyntaxKind.FirstNode) {
|
||||
scanner.setText((sourceFile || this.getSourceFile()).text);
|
||||
@@ -182,7 +183,7 @@ namespace ts {
|
||||
return this._children[index];
|
||||
}
|
||||
|
||||
public getChildren(sourceFile?: SourceFile): Node[] {
|
||||
public getChildren(sourceFile?: SourceFileLike): Node[] {
|
||||
if (!this._children) this.createChildren(sourceFile);
|
||||
return this._children;
|
||||
}
|
||||
@@ -231,7 +232,7 @@ namespace ts {
|
||||
return getSourceFileOfNode(this);
|
||||
}
|
||||
|
||||
public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
|
||||
public getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number {
|
||||
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
|
||||
}
|
||||
|
||||
@@ -1683,7 +1684,7 @@ namespace ts {
|
||||
return [];
|
||||
}
|
||||
|
||||
function getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[]): CodeAction[] {
|
||||
function getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[] {
|
||||
synchronizeHostData();
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
const span = { start, length: end - start };
|
||||
@@ -1701,7 +1702,8 @@ namespace ts {
|
||||
program: program,
|
||||
newLineCharacter: newLineChar,
|
||||
host: host,
|
||||
cancellationToken: cancellationToken
|
||||
cancellationToken: cancellationToken,
|
||||
rulesProvider: getRuleProvider(formatOptions)
|
||||
};
|
||||
|
||||
const fixes = codefix.getFixes(context);
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
/* @internal */
|
||||
namespace ts.textChanges {
|
||||
|
||||
/**
|
||||
* Currently for simplicity we store recovered positions on the node itself.
|
||||
* It can be changed to side-table later if we decide that current design is too invasive.
|
||||
*/
|
||||
function getPos(n: TextRange) {
|
||||
return (<any>n)["__pos"];
|
||||
}
|
||||
|
||||
function setPos(n: TextRange, pos: number) {
|
||||
(<any>n)["__pos"] = pos;
|
||||
}
|
||||
|
||||
function getEnd(n: TextRange) {
|
||||
return (<any>n)["__end"];
|
||||
}
|
||||
|
||||
function setEnd(n: TextRange, end: number) {
|
||||
(<any>n)["__end"] = end;
|
||||
}
|
||||
|
||||
export interface ConfigurableStart {
|
||||
useNonAdjustedStartPosition?: boolean;
|
||||
}
|
||||
export interface ConfigurableEnd {
|
||||
useNonAdjustedEndPosition?: boolean;
|
||||
}
|
||||
|
||||
export enum Position {
|
||||
FullStart,
|
||||
Start
|
||||
}
|
||||
|
||||
function skipWhitespacesAndLineBreaks(text: string, start: number) {
|
||||
return skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
}
|
||||
|
||||
function hasCommentsBeforeLineBreak(text: string, start: number) {
|
||||
let i = start;
|
||||
while (i < text.length) {
|
||||
const ch = text.charCodeAt(i);
|
||||
if (isWhiteSpaceSingleLine(ch)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
return ch === CharacterCodes.slash;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Usually node.pos points to a position immediately after the previous token.
|
||||
* If this position is used as a beginning of the span to remove - it might lead to removing the trailing trivia of the previous node, i.e:
|
||||
* const x; // this is x
|
||||
* ^ - pos for the next variable declaration will point here
|
||||
* const y; // this is y
|
||||
* ^ - end for previous variable declaration
|
||||
* Usually leading trivia of the variable declaration 'y' should not include trailing trivia (whitespace, comment 'this is x' and newline) from the preceding
|
||||
* variable declaration and trailing trivia for 'y' should include (whitespace, comment 'this is y', newline).
|
||||
* By default when removing nodes we adjust start and end positions to respect specification of the trivia above.
|
||||
* If pos\end should be interpreted literally 'useNonAdjustedStartPosition' or 'useNonAdjustedEndPosition' should be set to true
|
||||
*/
|
||||
export type ConfigurableStartEnd = ConfigurableStart & ConfigurableEnd;
|
||||
|
||||
export interface InsertNodeOptions {
|
||||
/**
|
||||
* Text to be inserted before the new node
|
||||
*/
|
||||
prefix?: string;
|
||||
/**
|
||||
* Text to be inserted after the new node
|
||||
*/
|
||||
suffix?: string;
|
||||
/**
|
||||
* Text of inserted node will be formatted with this indentation, otherwise indentation will be inferred from the old node
|
||||
*/
|
||||
indentation?: number;
|
||||
/**
|
||||
* Text of inserted node will be formatted with this delta, otherwise delta will be inferred from the new node kind
|
||||
*/
|
||||
delta?: number;
|
||||
}
|
||||
|
||||
export type ChangeNodeOptions = ConfigurableStartEnd & InsertNodeOptions;
|
||||
|
||||
interface Change {
|
||||
readonly sourceFile: SourceFile;
|
||||
readonly range: TextRange;
|
||||
readonly useIndentationFromFile?: boolean;
|
||||
readonly node?: Node;
|
||||
readonly options?: ChangeNodeOptions;
|
||||
}
|
||||
|
||||
export function getSeparatorCharacter(separator: Token<SyntaxKind.CommaToken | SyntaxKind.SemicolonToken>) {
|
||||
return tokenToString(separator.kind);
|
||||
}
|
||||
|
||||
export function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStart, position: Position) {
|
||||
if (options.useNonAdjustedStartPosition) {
|
||||
return node.getFullStart();
|
||||
}
|
||||
const fullStart = node.getFullStart();
|
||||
const start = node.getStart(sourceFile);
|
||||
if (fullStart === start) {
|
||||
return start;
|
||||
}
|
||||
const fullStartLine = getLineStartPositionForPosition(fullStart, sourceFile);
|
||||
const startLine = getLineStartPositionForPosition(start, sourceFile);
|
||||
if (startLine === fullStartLine) {
|
||||
// full start and start of the node are on the same line
|
||||
// a, b;
|
||||
// ^ ^
|
||||
// | start
|
||||
// fullstart
|
||||
// when b is replaced - we usually want to keep the leading trvia
|
||||
// when b is deleted - we delete it
|
||||
return position === Position.Start ? start : fullStart;
|
||||
}
|
||||
// get start position of the line following the line that contains fullstart position
|
||||
let adjustedStartPosition = getStartPositionOfLine(getLineOfLocalPosition(sourceFile, fullStartLine) + 1, sourceFile);
|
||||
// skip whitespaces/newlines
|
||||
adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition);
|
||||
return getStartPositionOfLine(getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile);
|
||||
}
|
||||
|
||||
export function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: ConfigurableEnd) {
|
||||
if (options.useNonAdjustedEndPosition) {
|
||||
return node.getEnd();
|
||||
}
|
||||
const end = node.getEnd();
|
||||
const newEnd = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true);
|
||||
// check if last character before newPos is linebreak
|
||||
// if yes - considered all skipped trivia to be trailing trivia of the node
|
||||
return newEnd !== end && isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))
|
||||
? newEnd
|
||||
: end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element
|
||||
*/
|
||||
function isSeparator(node: Node, candidate: Node): candidate is Token<SyntaxKind.CommaToken | SyntaxKind.SemicolonToken> {
|
||||
return candidate && node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression));
|
||||
}
|
||||
|
||||
function spaces(count: number) {
|
||||
let s = "";
|
||||
for (let i = 0; i < count; i++) {
|
||||
s += " ";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
export class ChangeTracker {
|
||||
private changes: Change[] = [];
|
||||
private readonly newLineCharacter: string;
|
||||
|
||||
public static fromCodeFixContext(context: CodeFixContext) {
|
||||
return new ChangeTracker(context.newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.rulesProvider);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly newLine: NewLineKind,
|
||||
private readonly rulesProvider: formatting.RulesProvider,
|
||||
private readonly validator?: (text: NonFormattedText) => void) {
|
||||
this.newLineCharacter = getNewLineCharacter({ newLine });
|
||||
}
|
||||
|
||||
public deleteNode(sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = {}) {
|
||||
const startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart);
|
||||
const endPosition = getAdjustedEndPosition(sourceFile, node, options);
|
||||
this.changes.push({ sourceFile, options, range: { pos: startPosition, end: endPosition } });
|
||||
return this;
|
||||
}
|
||||
|
||||
public deleteRange(sourceFile: SourceFile, range: TextRange) {
|
||||
this.changes.push({ sourceFile, range });
|
||||
return this;
|
||||
}
|
||||
|
||||
public deleteNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd = {}) {
|
||||
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart);
|
||||
const endPosition = getAdjustedEndPosition(sourceFile, endNode, options);
|
||||
this.changes.push({ sourceFile, options, range: { pos: startPosition, end: endPosition } });
|
||||
return this;
|
||||
}
|
||||
|
||||
public deleteNodeInList(sourceFile: SourceFile, node: Node) {
|
||||
const containingList = formatting.SmartIndenter.getContainingList(node, sourceFile);
|
||||
if (!containingList) {
|
||||
Debug.fail("node is not a list element");
|
||||
return this;
|
||||
}
|
||||
const index = containingList.indexOf(node);
|
||||
if (index < 0) {
|
||||
return this;
|
||||
}
|
||||
if (containingList.length === 1) {
|
||||
this.deleteNode(sourceFile, node);
|
||||
return this;
|
||||
}
|
||||
if (index !== containingList.length - 1) {
|
||||
const nextToken = getTokenAtPosition(sourceFile, node.end);
|
||||
if (nextToken && isSeparator(node, nextToken)) {
|
||||
// find first non-whitespace position in the leading trivia of the node
|
||||
const startPosition = skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
const nextElement = containingList[index + 1];
|
||||
/// find first non-whitespace position in the leading trivia of the next node
|
||||
const endPosition = skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, nextElement, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
// shift next node so its first non-whitespace position will be moved to the first non-whitespace position of the deleted node
|
||||
this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
|
||||
}
|
||||
}
|
||||
else {
|
||||
const previousToken = getTokenAtPosition(sourceFile, containingList[index - 1].end);
|
||||
if (previousToken && isSeparator(node, previousToken)) {
|
||||
this.deleteNodeRange(sourceFile, previousToken, node);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public replaceRange(sourceFile: SourceFile, range: TextRange, newNode: Node, options: InsertNodeOptions = {}) {
|
||||
this.changes.push({ sourceFile, range, options, node: newNode });
|
||||
return this;
|
||||
}
|
||||
|
||||
public replaceNode(sourceFile: SourceFile, oldNode: Node, newNode: Node, options: ChangeNodeOptions = {}) {
|
||||
const startPosition = getAdjustedStartPosition(sourceFile, oldNode, options, Position.Start);
|
||||
const endPosition = getAdjustedEndPosition(sourceFile, oldNode, options);
|
||||
this.changes.push({ sourceFile, options, useIndentationFromFile: true, node: newNode, range: { pos: startPosition, end: endPosition } });
|
||||
return this;
|
||||
}
|
||||
|
||||
public replaceNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, newNode: Node, options: ChangeNodeOptions = {}) {
|
||||
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.Start);
|
||||
const endPosition = getAdjustedEndPosition(sourceFile, endNode, options);
|
||||
this.changes.push({ sourceFile, options, useIndentationFromFile: true, node: newNode, range: { pos: startPosition, end: endPosition } });
|
||||
return this;
|
||||
}
|
||||
|
||||
public insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}) {
|
||||
this.changes.push({ sourceFile, options, node: newNode, range: { pos: pos, end: pos } });
|
||||
return this;
|
||||
}
|
||||
|
||||
public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, options: InsertNodeOptions & ConfigurableStart = {}) {
|
||||
const startPosition = getAdjustedStartPosition(sourceFile, before, options, Position.Start);
|
||||
this.changes.push({ sourceFile, options, useIndentationFromFile: true, node: newNode, range: { pos: startPosition, end: startPosition } });
|
||||
return this;
|
||||
}
|
||||
|
||||
public insertNodeAfter(sourceFile: SourceFile, after: Node, newNode: Node, options: InsertNodeOptions & ConfigurableEnd = {}) {
|
||||
if ((isStatementButNotDeclaration(after)) ||
|
||||
after.kind === SyntaxKind.PropertyDeclaration ||
|
||||
after.kind === SyntaxKind.PropertySignature ||
|
||||
after.kind === SyntaxKind.MethodSignature) {
|
||||
// check if previous statement ends with semicolon
|
||||
// if not - insert semicolon to preserve the code from changing the meaning due to ASI
|
||||
if (sourceFile.text.charCodeAt(after.end - 1) !== CharacterCodes.semicolon) {
|
||||
this.changes.push({
|
||||
sourceFile,
|
||||
options: {},
|
||||
range: { pos: after.end, end: after.end },
|
||||
node: createToken(SyntaxKind.SemicolonToken)
|
||||
})
|
||||
}
|
||||
}
|
||||
const endPosition = getAdjustedEndPosition(sourceFile, after, options);
|
||||
this.changes.push({ sourceFile, options, useIndentationFromFile: true, node: newNode, range: { pos: endPosition, end: endPosition } });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range,
|
||||
* i.e. arguments in arguments lists, parameters in parameter lists etc. Statements or class elements are different in sense that
|
||||
* for them separators are treated as the part of the node.
|
||||
*/
|
||||
public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node) {
|
||||
const containingList = formatting.SmartIndenter.getContainingList(after, sourceFile);
|
||||
if (!containingList) {
|
||||
Debug.fail("node is not a list element");
|
||||
return this;
|
||||
}
|
||||
const index = containingList.indexOf(after);
|
||||
if (index < 0) {
|
||||
return this;
|
||||
}
|
||||
const end = after.getEnd();
|
||||
if (index !== containingList.length - 1) {
|
||||
// any element except the last one
|
||||
// use next sibling as an anchor
|
||||
const nextToken = getTokenAtPosition(sourceFile, after.end);
|
||||
if (nextToken && isSeparator(after, nextToken)) {
|
||||
// for list
|
||||
// a, b, c
|
||||
// create change for adding 'e' after 'a' as
|
||||
// - find start of next element after a (it is b)
|
||||
// - use this start as start and end position in final change
|
||||
// - build text of change by formatting the text of node + separator + whitespace trivia of b
|
||||
|
||||
// in multiline case it will work as
|
||||
// a,
|
||||
// b,
|
||||
// c,
|
||||
// result - '*' denotes leading trivia that will be inserted after new text (displayed as '#')
|
||||
// a,*
|
||||
//***insertedtext<separator>#
|
||||
//###b,
|
||||
// c,
|
||||
// find line and character of the next element
|
||||
const lineAndCharOfNextElement = getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart()));
|
||||
// find line and character of the token that precedes next element (usually it is separator)
|
||||
const lineAndCharOfNextToken = getLineAndCharacterOfPosition(sourceFile, nextToken.end);
|
||||
let prefix: string;
|
||||
let startPos: number;
|
||||
if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) {
|
||||
// next element is located on the same line with separator:
|
||||
// a,$$$$b
|
||||
// ^ ^
|
||||
// | |-next element
|
||||
// |-separator
|
||||
// where $$$ is some leading trivia
|
||||
// for a newly inserted node we'll maintain the same relative position comparing to separator and replace leading trivia with spaces
|
||||
// a, x,$$$$b
|
||||
// ^ ^ ^
|
||||
// | | |-next element
|
||||
// | |-new inserted node padded with spaces
|
||||
// |-separator
|
||||
startPos = nextToken.end;
|
||||
prefix = spaces(lineAndCharOfNextElement.character - lineAndCharOfNextToken.character);
|
||||
}
|
||||
else {
|
||||
// next element is located on different line that separator
|
||||
// let insert position be the beginning of the line that contains next element
|
||||
startPos = getStartPositionOfLine(lineAndCharOfNextElement.line, sourceFile);
|
||||
}
|
||||
|
||||
this.changes.push({
|
||||
sourceFile,
|
||||
range: { pos: startPos, end: containingList[index + 1].getStart(sourceFile) },
|
||||
node: newNode,
|
||||
useIndentationFromFile: true,
|
||||
options: {
|
||||
prefix,
|
||||
// write separator and leading trivia of the next element as suffix
|
||||
suffix: `${tokenToString(nextToken.kind)}${sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile))}`
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
const afterStart = after.getStart(sourceFile);
|
||||
const afterStartLinePosition = getLineStartPositionForPosition(afterStart, sourceFile);
|
||||
|
||||
let separator: SyntaxKind.CommaToken | SyntaxKind.SemicolonToken;
|
||||
let multilineList = false;
|
||||
|
||||
// insert element after the last element in the list that has more than one item
|
||||
// pick the element preceding the after element to:
|
||||
// - pick the separator
|
||||
// - determine if list is a multiline
|
||||
if (containingList.length === 1) {
|
||||
// if list has only one element then we'll format is as multiline if node has comment in trailing trivia, or as singleline otherwise
|
||||
// i.e. var x = 1 // this is x
|
||||
// | new element will be inserted at this position
|
||||
separator = SyntaxKind.CommaToken;
|
||||
}
|
||||
else {
|
||||
// element has more than one element, pick separator from the list
|
||||
const tokenBeforeInsertPosition = findPrecedingToken(after.pos, sourceFile);
|
||||
separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : SyntaxKind.CommaToken;
|
||||
// determine if list is multiline by checking lines of after element and element that precedes it.
|
||||
const afterMinusOneStartLinePosition = getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile);
|
||||
multilineList = afterMinusOneStartLinePosition !== afterStartLinePosition;
|
||||
}
|
||||
if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) {
|
||||
// in this case we'll always treat containing list as multiline
|
||||
multilineList = true;
|
||||
}
|
||||
if (multilineList) {
|
||||
// insert separator immediately following the 'after' node to preserve comments in trailing trivia
|
||||
this.changes.push({
|
||||
sourceFile,
|
||||
range: { pos: end, end },
|
||||
node: createToken(separator),
|
||||
options: {}
|
||||
});
|
||||
// use the same indentation as 'after' item
|
||||
const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.rulesProvider.getFormatOptions());
|
||||
// insert element before the line break on the line that contains 'after' element
|
||||
let insertPos = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false);
|
||||
if (insertPos !== end && isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) {
|
||||
insertPos--
|
||||
}
|
||||
this.changes.push({
|
||||
sourceFile,
|
||||
range: { pos: insertPos, end: insertPos },
|
||||
node: newNode,
|
||||
options: { indentation, prefix: this.newLineCharacter }
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.changes.push({
|
||||
sourceFile,
|
||||
range: { pos: end, end },
|
||||
node: newNode,
|
||||
options: { prefix: `${tokenToString(separator)} ` }
|
||||
});
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public getChanges(): FileTextChanges[] {
|
||||
const changesPerFile = createFileMap<Change[]>();
|
||||
// group changes per file
|
||||
for (const c of this.changes) {
|
||||
let changesInFile = changesPerFile.get(c.sourceFile.path);
|
||||
if (!changesInFile) {
|
||||
changesPerFile.set(c.sourceFile.path, changesInFile = []);
|
||||
};
|
||||
changesInFile.push(c);
|
||||
}
|
||||
// convert changes
|
||||
const fileChangesList: FileTextChanges[] = [];
|
||||
changesPerFile.forEachValue(path => {
|
||||
const changesInFile = changesPerFile.get(path);
|
||||
const sourceFile = changesInFile[0].sourceFile;
|
||||
const fileTextChanges: FileTextChanges = { fileName: sourceFile.fileName, textChanges: [] };
|
||||
for (const c of ChangeTracker.normalize(changesInFile)) {
|
||||
fileTextChanges.textChanges.push({
|
||||
span: this.computeSpan(c, sourceFile),
|
||||
newText: this.computeNewText(c, sourceFile)
|
||||
});
|
||||
}
|
||||
fileChangesList.push(fileTextChanges);
|
||||
});
|
||||
|
||||
return fileChangesList;
|
||||
}
|
||||
|
||||
private computeSpan(change: Change, _sourceFile: SourceFile): TextSpan {
|
||||
return createTextSpanFromBounds(change.range.pos, change.range.end);
|
||||
}
|
||||
|
||||
private computeNewText(change: Change, sourceFile: SourceFile): string {
|
||||
if (!change.node) {
|
||||
// deletion case
|
||||
return "";
|
||||
}
|
||||
const options = change.options || {};
|
||||
const nonFormattedText = getNonformattedText(change.node, sourceFile, this.newLine);
|
||||
if (this.validator) {
|
||||
this.validator(nonFormattedText);
|
||||
}
|
||||
|
||||
const formatOptions = this.rulesProvider.getFormatOptions();
|
||||
const pos = change.range.pos;
|
||||
const posStartsLine = getLineStartPositionForPosition(pos, sourceFile) === pos;
|
||||
|
||||
const initialIndentation =
|
||||
change.options.indentation !== undefined
|
||||
? change.options.indentation
|
||||
: change.useIndentationFromFile
|
||||
? formatting.SmartIndenter.getIndentation(change.range.pos, sourceFile, formatOptions, posStartsLine || (change.options.prefix == this.newLineCharacter))
|
||||
: 0;
|
||||
const delta =
|
||||
change.options.delta !== undefined
|
||||
? change.options.delta
|
||||
: formatting.SmartIndenter.shouldIndentChildNode(change.node)
|
||||
? formatOptions.indentSize
|
||||
: 0;
|
||||
|
||||
let text = applyFormatting(nonFormattedText, sourceFile, initialIndentation, delta, this.rulesProvider);
|
||||
// strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line
|
||||
// however keep indentation if it is was forced
|
||||
text = posStartsLine || change.options.indentation !== undefined ? text : text.replace(/^\s+/, "");
|
||||
return (options.prefix || "") + text + (options.suffix || "");
|
||||
}
|
||||
|
||||
private static normalize(changes: Change[]) {
|
||||
// order changes by start position
|
||||
const normalized = stableSort(changes, (a, b) => a.range.pos - b.range.pos);
|
||||
// verify that end position of the change is less than start position of the next change
|
||||
for (let i = 0; i < normalized.length - 2; i++) {
|
||||
Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
export interface NonFormattedText {
|
||||
readonly text: string;
|
||||
readonly node: Node;
|
||||
}
|
||||
|
||||
export function getNonformattedText(node: Node, sourceFile: SourceFile, newLine: NewLineKind): NonFormattedText {
|
||||
const options = { newLine, target: sourceFile.languageVersion };
|
||||
const writer = new Writer(getNewLineCharacter(options));
|
||||
const printer = createPrinter(options, writer);
|
||||
printer.writeNode(EmitHint.Unspecified, node, sourceFile, writer);
|
||||
return { text: writer.getText(), node: assignPositionsToNode(node) };
|
||||
}
|
||||
|
||||
export function applyFormatting(nonFormattedText: NonFormattedText, sourceFile: SourceFile, initialIndentation: number, delta: number, rulesProvider: formatting.RulesProvider) {
|
||||
const lineMap = computeLineStarts(nonFormattedText.text);
|
||||
const file: SourceFileLike = {
|
||||
text: nonFormattedText.text,
|
||||
lineMap,
|
||||
getLineAndCharacterOfPosition: pos => computeLineAndCharacterOfPosition(lineMap, pos)
|
||||
};
|
||||
const changes = formatting.formatNode(nonFormattedText.node, file, sourceFile.languageVariant, initialIndentation, delta, rulesProvider);
|
||||
return applyChanges(nonFormattedText.text, changes);
|
||||
}
|
||||
|
||||
export function applyChanges(text: string, changes: TextChange[]): string {
|
||||
for (let i = changes.length - 1; i >= 0; i--) {
|
||||
const change = changes[i];
|
||||
text = `${text.substring(0, change.span.start)}${change.newText}${text.substring(textSpanEnd(change.span))}`;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function isTrivia(s: string) {
|
||||
return skipTrivia(s, 0) === s.length;
|
||||
}
|
||||
|
||||
const nullTransformationContext: TransformationContext = {
|
||||
enableEmitNotification: noop,
|
||||
enableSubstitution: noop,
|
||||
endLexicalEnvironment: () => undefined,
|
||||
getCompilerOptions: notImplemented,
|
||||
getEmitHost: notImplemented,
|
||||
getEmitResolver: notImplemented,
|
||||
hoistFunctionDeclaration: noop,
|
||||
hoistVariableDeclaration: noop,
|
||||
isEmitNotificationEnabled: notImplemented,
|
||||
isSubstitutionEnabled: notImplemented,
|
||||
onEmitNode: noop,
|
||||
onSubstituteNode: notImplemented,
|
||||
readEmitHelpers: notImplemented,
|
||||
requestEmitHelper: noop,
|
||||
resumeLexicalEnvironment: noop,
|
||||
startLexicalEnvironment: noop,
|
||||
suspendLexicalEnvironment: noop
|
||||
};
|
||||
|
||||
function assignPositionsToNode(node: Node): Node {
|
||||
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray);
|
||||
// create proxy node for non synthesized nodes
|
||||
const newNode = nodeIsSynthesized(visited)
|
||||
? visited
|
||||
: (Proxy.prototype = visited, new (<any>Proxy)());
|
||||
newNode.pos = getPos(node);
|
||||
newNode.end = getEnd(node);
|
||||
return newNode;
|
||||
|
||||
function Proxy() { }
|
||||
}
|
||||
|
||||
function assignPositionsToNodeArray(nodes: NodeArray<any>, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) {
|
||||
const visited = visitNodes(nodes, visitor, test, start, count);
|
||||
if (!visited) {
|
||||
return visited;
|
||||
}
|
||||
// clone nodearray if necessary
|
||||
const nodeArray = visited === nodes ? createNodeArray(visited.slice(0)) : visited;
|
||||
nodeArray.pos = getPos(nodes);
|
||||
nodeArray.end = getEnd(nodes);
|
||||
return nodeArray;
|
||||
}
|
||||
|
||||
class Writer implements EmitTextWriter, PrintHandlers {
|
||||
private lastNonTriviaPosition = 0;
|
||||
private readonly writer: EmitTextWriter;
|
||||
|
||||
public readonly onEmitNode: PrintHandlers["onEmitNode"];
|
||||
public readonly onBeforeEmitNodeArray: PrintHandlers["onBeforeEmitNodeArray"];
|
||||
public readonly onAfterEmitNodeArray: PrintHandlers["onAfterEmitNodeArray"];
|
||||
|
||||
constructor(newLine: string) {
|
||||
this.writer = createTextWriter(newLine);
|
||||
this.onEmitNode = (hint, node, printCallback) => {
|
||||
if (node) {
|
||||
setPos(node, this.lastNonTriviaPosition);
|
||||
}
|
||||
printCallback(hint, node);
|
||||
if (node) {
|
||||
setEnd(node, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
this.onBeforeEmitNodeArray = nodes => {
|
||||
if (nodes) {
|
||||
setPos(nodes, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
this.onAfterEmitNodeArray = nodes => {
|
||||
if (nodes) {
|
||||
setEnd(nodes, this.lastNonTriviaPosition);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private setLastNonTriviaPosition(s: string, force: boolean) {
|
||||
if (force || !isTrivia(s)) {
|
||||
this.lastNonTriviaPosition = this.writer.getTextPos();
|
||||
let i = 0;
|
||||
while (isWhiteSpace(s.charCodeAt(s.length - i - 1))) {
|
||||
i++;
|
||||
}
|
||||
// trim trailing whitespaces
|
||||
this.lastNonTriviaPosition -= i;
|
||||
}
|
||||
}
|
||||
|
||||
write(s: string): void {
|
||||
this.writer.write(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeTextOfNode(text: string, node: Node): void {
|
||||
this.writer.writeTextOfNode(text, node);
|
||||
}
|
||||
writeLine(): void {
|
||||
this.writer.writeLine();
|
||||
}
|
||||
increaseIndent(): void {
|
||||
this.writer.increaseIndent();
|
||||
}
|
||||
decreaseIndent(): void {
|
||||
this.writer.decreaseIndent();
|
||||
}
|
||||
getText(): string {
|
||||
return this.writer.getText();
|
||||
}
|
||||
rawWrite(s: string): void {
|
||||
this.writer.rawWrite(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeLiteral(s: string): void {
|
||||
this.writer.writeLiteral(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ true);
|
||||
}
|
||||
getTextPos(): number {
|
||||
return this.writer.getTextPos();
|
||||
}
|
||||
getLine(): number {
|
||||
return this.writer.getLine();
|
||||
}
|
||||
getColumn(): number {
|
||||
return this.writer.getColumn();
|
||||
}
|
||||
getIndent(): number {
|
||||
return this.writer.getIndent();
|
||||
}
|
||||
isAtStartOfLine(): boolean {
|
||||
return this.writer.isAtStartOfLine();
|
||||
}
|
||||
reset(): void {
|
||||
this.writer.reset();
|
||||
this.lastNonTriviaPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@
|
||||
"shims.ts",
|
||||
"signatureHelp.ts",
|
||||
"symbolDisplay.ts",
|
||||
"textChanges.ts",
|
||||
"formatting/formatting.ts",
|
||||
"formatting/formattingContext.ts",
|
||||
"formatting/formattingRequestKind.ts",
|
||||
|
||||
@@ -4,7 +4,11 @@ namespace ts {
|
||||
getChildCount(sourceFile?: SourceFile): number;
|
||||
getChildAt(index: number, sourceFile?: SourceFile): Node;
|
||||
getChildren(sourceFile?: SourceFile): Node[];
|
||||
/* @internal */
|
||||
getChildren(sourceFile?: SourceFileLike): Node[];
|
||||
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
|
||||
/* @internal */
|
||||
getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number;
|
||||
getFullStart(): number;
|
||||
getEnd(): number;
|
||||
getWidth(sourceFile?: SourceFile): number;
|
||||
@@ -59,6 +63,10 @@ namespace ts {
|
||||
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
|
||||
}
|
||||
|
||||
export interface SourceFileLike {
|
||||
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an immutable snapshot of a script at a specified time.Once acquired, the
|
||||
* snapshot is observably immutable. i.e. the same calls with the same parameters will return
|
||||
@@ -248,7 +256,7 @@ namespace ts {
|
||||
|
||||
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
|
||||
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[]): CodeAction[];
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[];
|
||||
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
|
||||
|
||||
|
||||
@@ -394,8 +394,8 @@ namespace ts {
|
||||
list: Node;
|
||||
}
|
||||
|
||||
export function getLineStartPositionForPosition(position: number, sourceFile: SourceFile): number {
|
||||
const lineStarts = sourceFile.getLineStarts();
|
||||
export function getLineStartPositionForPosition(position: number, sourceFile: SourceFileLike): number {
|
||||
const lineStarts = getLineStarts(sourceFile);
|
||||
const line = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
return lineStarts[line];
|
||||
}
|
||||
@@ -604,7 +604,7 @@ namespace ts {
|
||||
return !!findChildOfKind(n, kind, sourceFile);
|
||||
}
|
||||
|
||||
export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node | undefined {
|
||||
export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFileLike): Node | undefined {
|
||||
return forEach(n.getChildren(sourceFile), c => c.kind === kind && c);
|
||||
}
|
||||
|
||||
@@ -1003,10 +1003,6 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function isToken(n: Node): boolean {
|
||||
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
|
||||
}
|
||||
|
||||
export function isWord(kind: SyntaxKind): boolean {
|
||||
return kind === SyntaxKind.Identifier || isKeyword(kind);
|
||||
}
|
||||
@@ -1384,9 +1380,9 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function getOpenBraceEnd(constructor: ConstructorDeclaration, sourceFile: SourceFile) {
|
||||
export function getOpenBrace(constructor: ConstructorDeclaration, sourceFile: SourceFile) {
|
||||
// First token is the open curly, this is where we want to put the 'super' call.
|
||||
return constructor.body.getFirstToken(sourceFile).getEnd();
|
||||
return constructor.body.getFirstToken(sourceFile);
|
||||
}
|
||||
|
||||
export function getFirstNonSpaceCharacterPosition(text: string, position: number) {
|
||||
|
||||
Reference in New Issue
Block a user