mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-21 21:34:47 -06:00
Merge branch 'master' into dynamicNames
This commit is contained in:
commit
e81c83cdc7
@ -2430,15 +2430,6 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
|
||||
interface NodeBuilderContext {
|
||||
enclosingDeclaration: Node | undefined;
|
||||
flags: NodeBuilderFlags | undefined;
|
||||
|
||||
// State
|
||||
encounteredError: boolean;
|
||||
symbolStack: Symbol[] | undefined;
|
||||
}
|
||||
|
||||
function createNodeBuilderContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): NodeBuilderContext {
|
||||
return {
|
||||
enclosingDeclaration,
|
||||
@ -3037,30 +3028,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNameOfSymbol(symbol: Symbol, context: NodeBuilderContext): string {
|
||||
const declaration = firstOrUndefined(symbol.declarations);
|
||||
if (declaration) {
|
||||
const name = getNameOfDeclaration(declaration);
|
||||
if (name) {
|
||||
return declarationNameToString(name);
|
||||
}
|
||||
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
|
||||
}
|
||||
if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) {
|
||||
context.encounteredError = true;
|
||||
}
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.ClassExpression:
|
||||
return "(Anonymous class)";
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return "(Anonymous function)";
|
||||
}
|
||||
}
|
||||
return unescapeLeadingUnderscores(symbol.escapedName);
|
||||
}
|
||||
}
|
||||
|
||||
function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Declaration, flags?: TypeFormatFlags): string {
|
||||
@ -3125,7 +3092,16 @@ namespace ts {
|
||||
return type.flags & TypeFlags.StringLiteral ? '"' + escapeString((<StringLiteralType>type).value) + '"' : "" + (<NumberLiteralType>type).value;
|
||||
}
|
||||
|
||||
function getNameOfSymbol(symbol: Symbol): string {
|
||||
interface NodeBuilderContext {
|
||||
enclosingDeclaration: Node | undefined;
|
||||
flags: NodeBuilderFlags | undefined;
|
||||
|
||||
// State
|
||||
encounteredError: boolean;
|
||||
symbolStack: Symbol[] | undefined;
|
||||
}
|
||||
|
||||
function getNameOfSymbol(symbol: Symbol, context?: NodeBuilderContext): string {
|
||||
if (symbol.declarations && symbol.declarations.length) {
|
||||
const declaration = symbol.declarations[0];
|
||||
const name = getNameOfDeclaration(declaration);
|
||||
@ -3135,6 +3111,9 @@ namespace ts {
|
||||
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
|
||||
}
|
||||
if (context && !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) {
|
||||
context.encounteredError = true;
|
||||
}
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.ClassExpression:
|
||||
return "(Anonymous class)";
|
||||
@ -13436,16 +13415,11 @@ namespace ts {
|
||||
// the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature,
|
||||
// it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated
|
||||
// type of T.
|
||||
function getContextualTypeForElementExpression(node: Expression): Type {
|
||||
const arrayLiteral = <ArrayLiteralExpression>node.parent;
|
||||
const type = getApparentTypeOfContextualType(arrayLiteral);
|
||||
if (type) {
|
||||
const index = indexOf(arrayLiteral.elements, node);
|
||||
return getTypeOfPropertyOfContextualType(type, "" + index as __String)
|
||||
|| getIndexTypeOfContextualType(type, IndexKind.Number)
|
||||
|| getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false);
|
||||
}
|
||||
return undefined;
|
||||
function getContextualTypeForElementExpression(arrayContextualType: Type | undefined, index: number): Type | undefined {
|
||||
return arrayContextualType && (
|
||||
getTypeOfPropertyOfContextualType(arrayContextualType, "" + index as __String)
|
||||
|| getIndexTypeOfContextualType(arrayContextualType, IndexKind.Number)
|
||||
|| getIteratedTypeOrElementType(arrayContextualType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false));
|
||||
}
|
||||
|
||||
// In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type.
|
||||
@ -13559,15 +13533,21 @@ namespace ts {
|
||||
return getContextualTypeForObjectLiteralElement(<ObjectLiteralElementLike>parent);
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
return getApparentTypeOfContextualType(parent.parent as ObjectLiteralExpression);
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return getContextualTypeForElementExpression(node);
|
||||
case SyntaxKind.ArrayLiteralExpression: {
|
||||
const arrayLiteral = <ArrayLiteralExpression>parent;
|
||||
const type = getApparentTypeOfContextualType(arrayLiteral);
|
||||
return getContextualTypeForElementExpression(type, indexOfNode(arrayLiteral.elements, node));
|
||||
}
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return getContextualTypeForConditionalOperand(node);
|
||||
case SyntaxKind.TemplateSpan:
|
||||
Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression);
|
||||
return getContextualTypeForSubstitutionExpression(<TemplateExpression>parent.parent, node);
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return getContextualType(<ParenthesizedExpression>parent);
|
||||
case SyntaxKind.ParenthesizedExpression: {
|
||||
// Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast.
|
||||
const tag = isInJavaScriptFile(parent) ? getJSDocTypeTag(parent) : undefined;
|
||||
return tag ? getTypeFromTypeNode(tag.typeExpression.type) : getContextualType(<ParenthesizedExpression>parent);
|
||||
}
|
||||
case SyntaxKind.JsxExpression:
|
||||
return getContextualTypeForJsxExpression(<JsxExpression>parent);
|
||||
case SyntaxKind.JsxAttribute:
|
||||
@ -13689,12 +13669,14 @@ namespace ts {
|
||||
(node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.EqualsToken);
|
||||
}
|
||||
|
||||
function checkArrayLiteral(node: ArrayLiteralExpression, checkMode?: CheckMode): Type {
|
||||
function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined): Type {
|
||||
const elements = node.elements;
|
||||
let hasSpreadElement = false;
|
||||
const elementTypes: Type[] = [];
|
||||
const inDestructuringPattern = isAssignmentTarget(node);
|
||||
for (const e of elements) {
|
||||
const contextualType = getApparentTypeOfContextualType(node);
|
||||
for (let index = 0; index < elements.length; index++) {
|
||||
const e = elements[index];
|
||||
if (inDestructuringPattern && e.kind === SyntaxKind.SpreadElement) {
|
||||
// Given the following situation:
|
||||
// var c: {};
|
||||
@ -13716,7 +13698,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
const type = checkExpressionForMutableLocation(e, checkMode);
|
||||
const elementContextualType = getContextualTypeForElementExpression(contextualType, index);
|
||||
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType);
|
||||
elementTypes.push(type);
|
||||
}
|
||||
hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElement;
|
||||
@ -18305,9 +18288,13 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkExpressionForMutableLocation(node: Expression, checkMode?: CheckMode): Type {
|
||||
function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode, contextualType?: Type): Type {
|
||||
if (arguments.length === 2) {
|
||||
contextualType = getContextualType(node);
|
||||
}
|
||||
const type = checkExpression(node, checkMode);
|
||||
return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type);
|
||||
const shouldWiden = isTypeAssertion(node) || isLiteralContextualType(contextualType);
|
||||
return shouldWiden ? type : getWidenedLiteralType(type);
|
||||
}
|
||||
|
||||
function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type {
|
||||
@ -18425,13 +18412,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type {
|
||||
if (isInJavaScriptFile(node) && node.jsDoc) {
|
||||
const typecasts = flatMap(node.jsDoc, doc => filter(doc.tags, tag => tag.kind === SyntaxKind.JSDocTypeTag && !!(tag as JSDocTypeTag).typeExpression && !!(tag as JSDocTypeTag).typeExpression.type));
|
||||
if (typecasts && typecasts.length) {
|
||||
// We should have already issued an error if there were multiple type jsdocs
|
||||
const cast = typecasts[0] as JSDocTypeTag;
|
||||
return checkAssertionWorker(cast, cast.typeExpression.type, node.expression, checkMode);
|
||||
}
|
||||
const tag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined;
|
||||
if (tag) {
|
||||
return checkAssertionWorker(tag, tag.typeExpression.type, node.expression, checkMode);
|
||||
}
|
||||
return checkExpression(node.expression, checkMode);
|
||||
}
|
||||
|
||||
@ -994,11 +994,6 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Gets the owned, enumerable property keys of a map-like.
|
||||
*
|
||||
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
|
||||
* Object.keys instead as it offers better performance.
|
||||
*
|
||||
* @param map A map-like.
|
||||
*/
|
||||
export function getOwnKeys<T>(map: MapLike<T>): string[] {
|
||||
const keys: string[] = [];
|
||||
@ -1011,6 +1006,17 @@ namespace ts {
|
||||
return keys;
|
||||
}
|
||||
|
||||
export function getOwnValues<T>(sparseArray: T[]): T[] {
|
||||
const values: T[] = [];
|
||||
for (const key in sparseArray) {
|
||||
if (hasOwnProperty.call(sparseArray, key)) {
|
||||
values.push(sparseArray[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/** Shims `Array.from`. */
|
||||
export function arrayFrom<T, U>(iterator: Iterator<T>, map: (t: T) => U): U[];
|
||||
export function arrayFrom<T>(iterator: Iterator<T>): T[];
|
||||
|
||||
@ -6149,11 +6149,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Parses out a JSDoc type expression.
|
||||
/* @internal */
|
||||
export function parseJSDocTypeExpression(): JSDocTypeExpression {
|
||||
export function parseJSDocTypeExpression(): JSDocTypeExpression;
|
||||
export function parseJSDocTypeExpression(requireBraces: true): JSDocTypeExpression | undefined;
|
||||
export function parseJSDocTypeExpression(requireBraces?: boolean): JSDocTypeExpression | undefined {
|
||||
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
|
||||
|
||||
parseExpected(SyntaxKind.OpenBraceToken);
|
||||
if (!parseExpected(SyntaxKind.OpenBraceToken) && requireBraces) {
|
||||
return undefined;
|
||||
}
|
||||
result.type = doInsideOfContext(NodeFlags.JSDoc, parseType);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
|
||||
@ -6500,14 +6503,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function tryParseTypeExpression(): JSDocTypeExpression | undefined {
|
||||
return tryParse(() => {
|
||||
skipWhitespace();
|
||||
if (token() !== SyntaxKind.OpenBraceToken) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parseJSDocTypeExpression();
|
||||
});
|
||||
skipWhitespace();
|
||||
return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
|
||||
}
|
||||
|
||||
function parseBracketNameInPropertyAndParamTag(): { name: EntityName, isBracketed: boolean } {
|
||||
@ -6616,7 +6613,7 @@ namespace ts {
|
||||
const result = <JSDocTypeTag>createNode(SyntaxKind.JSDocTypeTag, atToken.pos);
|
||||
result.atToken = atToken;
|
||||
result.tagName = tagName;
|
||||
result.typeExpression = tryParseTypeExpression();
|
||||
result.typeExpression = parseJSDocTypeExpression(/*mayBail*/ true);
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
|
||||
@ -14,21 +14,29 @@ namespace ts {
|
||||
return getSymbolWalker;
|
||||
|
||||
function getSymbolWalker(accept: (symbol: Symbol) => boolean = () => true): SymbolWalker {
|
||||
const visitedTypes = createMap<Type>(); // Key is id as string
|
||||
const visitedSymbols = createMap<Symbol>(); // Key is id as string
|
||||
const visitedTypes: Type[] = []; // Sparse array from id to type
|
||||
const visitedSymbols: Symbol[] = []; // Sparse array from id to symbol
|
||||
|
||||
return {
|
||||
walkType: type => {
|
||||
visitedTypes.clear();
|
||||
visitedSymbols.clear();
|
||||
visitType(type);
|
||||
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) };
|
||||
try {
|
||||
visitType(type);
|
||||
return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) };
|
||||
}
|
||||
finally {
|
||||
clear(visitedTypes);
|
||||
clear(visitedSymbols);
|
||||
}
|
||||
},
|
||||
walkSymbol: symbol => {
|
||||
visitedTypes.clear();
|
||||
visitedSymbols.clear();
|
||||
visitSymbol(symbol);
|
||||
return { visitedTypes: arrayFrom(visitedTypes.values()), visitedSymbols: arrayFrom(visitedSymbols.values()) };
|
||||
try {
|
||||
visitSymbol(symbol);
|
||||
return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) };
|
||||
}
|
||||
finally {
|
||||
clear(visitedTypes);
|
||||
clear(visitedSymbols);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@ -37,11 +45,10 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeIdString = type.id.toString();
|
||||
if (visitedTypes.has(typeIdString)) {
|
||||
if (visitedTypes[type.id]) {
|
||||
return;
|
||||
}
|
||||
visitedTypes.set(typeIdString, type);
|
||||
visitedTypes[type.id] = type;
|
||||
|
||||
// Reuse visitSymbol to visit the type's symbol,
|
||||
// but be sure to bail on recuring into the type if accept declines the symbol.
|
||||
@ -79,18 +86,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function visitTypeList(types: Type[]): void {
|
||||
if (!types) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
visitType(types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function visitTypeReference(type: TypeReference): void {
|
||||
visitType(type.target);
|
||||
visitTypeList(type.typeArguments);
|
||||
forEach(type.typeArguments, visitType);
|
||||
}
|
||||
|
||||
function visitTypeParameter(type: TypeParameter): void {
|
||||
@ -98,7 +96,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitUnionOrIntersectionType(type: UnionOrIntersectionType): void {
|
||||
visitTypeList(type.types);
|
||||
forEach(type.types, visitType);
|
||||
}
|
||||
|
||||
function visitIndexType(type: IndexType): void {
|
||||
@ -122,7 +120,7 @@ namespace ts {
|
||||
if (signature.typePredicate) {
|
||||
visitType(signature.typePredicate.type);
|
||||
}
|
||||
visitTypeList(signature.typeParameters);
|
||||
forEach(signature.typeParameters, visitType);
|
||||
|
||||
for (const parameter of signature.parameters){
|
||||
visitSymbol(parameter);
|
||||
@ -133,8 +131,8 @@ namespace ts {
|
||||
|
||||
function visitInterfaceType(interfaceT: InterfaceType): void {
|
||||
visitObjectType(interfaceT);
|
||||
visitTypeList(interfaceT.typeParameters);
|
||||
visitTypeList(getBaseTypes(interfaceT));
|
||||
forEach(interfaceT.typeParameters, visitType);
|
||||
forEach(getBaseTypes(interfaceT), visitType);
|
||||
visitType(interfaceT.thisType);
|
||||
}
|
||||
|
||||
@ -161,11 +159,11 @@ namespace ts {
|
||||
if (!symbol) {
|
||||
return;
|
||||
}
|
||||
const symbolIdString = getSymbolId(symbol).toString();
|
||||
if (visitedSymbols.has(symbolIdString)) {
|
||||
const symbolId = getSymbolId(symbol);
|
||||
if (visitedSymbols[symbolId]) {
|
||||
return;
|
||||
}
|
||||
visitedSymbols.set(symbolIdString, symbol);
|
||||
visitedSymbols[symbolId] = symbol;
|
||||
if (!accept(symbol)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4116,8 +4116,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface CompilerHost extends ModuleResolutionHost {
|
||||
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
|
||||
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
|
||||
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
|
||||
getSourceFileByPath?(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined;
|
||||
getCancellationToken?(): CancellationToken;
|
||||
getDefaultLibFileName(options: CompilerOptions): string;
|
||||
getDefaultLibLocation?(): string;
|
||||
|
||||
@ -321,6 +321,18 @@ namespace ts {
|
||||
return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: it is expected that the `nodeArray` and the `node` are within the same file.
|
||||
* For example, searching for a `SourceFile` in a `SourceFile[]` wouldn't work.
|
||||
*/
|
||||
export function indexOfNode(nodeArray: ReadonlyArray<Node>, node: Node) {
|
||||
return binarySearch(nodeArray, node, compareNodePos);
|
||||
}
|
||||
|
||||
function compareNodePos({ pos: aPos }: Node, { pos: bPos}: Node) {
|
||||
return aPos < bPos ? Comparison.LessThan : bPos < aPos ? Comparison.GreaterThan : Comparison.EqualTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets flags that control emit behavior of a node.
|
||||
*/
|
||||
@ -4091,9 +4103,14 @@ namespace ts {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocTemplateTag) as JSDocTemplateTag;
|
||||
}
|
||||
|
||||
/** Gets the JSDoc type tag for the node if present */
|
||||
/** Gets the JSDoc type tag for the node if present and valid */
|
||||
export function getJSDocTypeTag(node: Node): JSDocTypeTag | undefined {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
|
||||
// We should have already issued an error if there were multiple type jsdocs, so just use the first one.
|
||||
const tag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
|
||||
if (tag && tag.typeExpression && tag.typeExpression.type) {
|
||||
return tag;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -44,7 +44,8 @@ namespace Harness.Parallel.Host {
|
||||
console.log("Discovering tests...");
|
||||
const discoverStart = +(new Date());
|
||||
const { statSync }: { statSync(path: string): { size: number }; } = require("fs");
|
||||
const tasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
|
||||
let tasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
|
||||
const newTasks: { runner: TestRunnerKind, file: string, size: number }[] = [];
|
||||
const perfData = readSavedPerfData();
|
||||
let totalCost = 0;
|
||||
let unknownValue: string | undefined;
|
||||
@ -60,8 +61,10 @@ namespace Harness.Parallel.Host {
|
||||
const hashedName = hashName(runner.kind(), file);
|
||||
size = perfData[hashedName];
|
||||
if (size === undefined) {
|
||||
size = Number.MAX_SAFE_INTEGER;
|
||||
size = 0;
|
||||
unknownValue = hashedName;
|
||||
newTasks.push({ runner: runner.kind(), file, size });
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tasks.push({ runner: runner.kind(), file, size });
|
||||
@ -69,6 +72,7 @@ namespace Harness.Parallel.Host {
|
||||
}
|
||||
}
|
||||
tasks.sort((a, b) => a.size - b.size);
|
||||
tasks = tasks.concat(newTasks);
|
||||
// 1 fewer batches than threads to account for unittests running on the final thread
|
||||
const batchCount = runners.length === 1 ? workerCount : workerCount - 1;
|
||||
const packfraction = 0.9;
|
||||
@ -174,7 +178,7 @@ namespace Harness.Parallel.Host {
|
||||
let scheduledTotal = 0;
|
||||
batcher: while (true) {
|
||||
for (let i = 0; i < batchCount; i++) {
|
||||
if (tasks.length === 0) {
|
||||
if (tasks.length <= workerCount) { // Keep a small reserve even in the suboptimally packed case
|
||||
console.log(`Suboptimal packing detected: no tests remain to be stolen. Reduce packing fraction from ${packfraction} to fix.`);
|
||||
break batcher;
|
||||
}
|
||||
@ -213,7 +217,9 @@ namespace Harness.Parallel.Host {
|
||||
worker.send({ type: "batch", payload });
|
||||
}
|
||||
else { // Unittest thread - send off just one test
|
||||
worker.send({ type: "test", payload: tasks.pop() });
|
||||
const payload = tasks.pop();
|
||||
ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios
|
||||
worker.send({ type: "test", payload });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,6 +139,11 @@ namespace ts {
|
||||
`/**
|
||||
* @param
|
||||
*/`);
|
||||
|
||||
parsesIncorrectly("noType",
|
||||
`/**
|
||||
* @type
|
||||
*/`);
|
||||
});
|
||||
|
||||
describe("parsesCorrectly", () => {
|
||||
@ -148,12 +153,6 @@ namespace ts {
|
||||
*/`);
|
||||
|
||||
|
||||
parsesCorrectly("noType",
|
||||
`/**
|
||||
* @type
|
||||
*/`);
|
||||
|
||||
|
||||
parsesCorrectly("noReturnType",
|
||||
`/**
|
||||
* @return
|
||||
|
||||
@ -53,28 +53,19 @@ namespace ts.formatting {
|
||||
return res;
|
||||
|
||||
function advance(): void {
|
||||
Debug.assert(scanner !== undefined, "Scanner should be present");
|
||||
|
||||
lastTokenInfo = undefined;
|
||||
const isStarted = scanner.getStartPos() !== startPos;
|
||||
|
||||
if (isStarted) {
|
||||
if (trailingTrivia) {
|
||||
Debug.assert(trailingTrivia.length !== 0);
|
||||
wasNewLine = lastOrUndefined(trailingTrivia).kind === SyntaxKind.NewLineTrivia;
|
||||
}
|
||||
else {
|
||||
wasNewLine = false;
|
||||
}
|
||||
wasNewLine = trailingTrivia && lastOrUndefined(trailingTrivia)!.kind === SyntaxKind.NewLineTrivia;
|
||||
}
|
||||
else {
|
||||
scanner.scan();
|
||||
}
|
||||
|
||||
leadingTrivia = undefined;
|
||||
trailingTrivia = undefined;
|
||||
|
||||
if (!isStarted) {
|
||||
scanner.scan();
|
||||
}
|
||||
|
||||
let pos = scanner.getStartPos();
|
||||
|
||||
// Read leading trivia and token
|
||||
@ -94,25 +85,20 @@ namespace ts.formatting {
|
||||
|
||||
pos = scanner.getStartPos();
|
||||
|
||||
if (!leadingTrivia) {
|
||||
leadingTrivia = [];
|
||||
}
|
||||
leadingTrivia.push(item);
|
||||
leadingTrivia = append(leadingTrivia, item);
|
||||
}
|
||||
|
||||
savedPos = scanner.getStartPos();
|
||||
}
|
||||
|
||||
function shouldRescanGreaterThanToken(node: Node): boolean {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.GreaterThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanToken:
|
||||
return true;
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.GreaterThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanToken:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -134,7 +120,7 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
function shouldRescanJsxText(node: Node): boolean {
|
||||
return node && node.kind === SyntaxKind.JsxText;
|
||||
return node.kind === SyntaxKind.JsxText;
|
||||
}
|
||||
|
||||
function shouldRescanSlashToken(container: Node): boolean {
|
||||
@ -151,16 +137,7 @@ namespace ts.formatting {
|
||||
}
|
||||
|
||||
function readTokenInfo(n: Node): TokenInfo {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
if (!isOnToken()) {
|
||||
// scanner is not on the token (either advance was not called yet or scanner is already past the end position)
|
||||
return {
|
||||
leadingTrivia,
|
||||
trailingTrivia: undefined,
|
||||
token: undefined
|
||||
};
|
||||
}
|
||||
Debug.assert(isOnToken());
|
||||
|
||||
// normally scanner returns the smallest available token
|
||||
// check the kind of context node to determine if scanner should have more greedy behavior and consume more text.
|
||||
@ -194,33 +171,7 @@ namespace ts.formatting {
|
||||
scanner.scan();
|
||||
}
|
||||
|
||||
let currentToken = scanner.getToken();
|
||||
|
||||
if (expectedScanAction === ScanAction.RescanGreaterThanToken && currentToken === SyntaxKind.GreaterThanToken) {
|
||||
currentToken = scanner.reScanGreaterToken();
|
||||
Debug.assert(n.kind === currentToken);
|
||||
lastScanAction = ScanAction.RescanGreaterThanToken;
|
||||
}
|
||||
else if (expectedScanAction === ScanAction.RescanSlashToken && startsWithSlashToken(currentToken)) {
|
||||
currentToken = scanner.reScanSlashToken();
|
||||
Debug.assert(n.kind === currentToken);
|
||||
lastScanAction = ScanAction.RescanSlashToken;
|
||||
}
|
||||
else if (expectedScanAction === ScanAction.RescanTemplateToken && currentToken === SyntaxKind.CloseBraceToken) {
|
||||
currentToken = scanner.reScanTemplateToken();
|
||||
lastScanAction = ScanAction.RescanTemplateToken;
|
||||
}
|
||||
else if (expectedScanAction === ScanAction.RescanJsxIdentifier) {
|
||||
currentToken = scanner.scanJsxIdentifier();
|
||||
lastScanAction = ScanAction.RescanJsxIdentifier;
|
||||
}
|
||||
else if (expectedScanAction === ScanAction.RescanJsxText) {
|
||||
currentToken = scanner.reScanJsxToken();
|
||||
lastScanAction = ScanAction.RescanJsxText;
|
||||
}
|
||||
else {
|
||||
lastScanAction = ScanAction.Scan;
|
||||
}
|
||||
let currentToken = getNextToken(n, expectedScanAction);
|
||||
|
||||
const token: TextRangeWithKind = {
|
||||
pos: scanner.getStartPos(),
|
||||
@ -261,9 +212,47 @@ namespace ts.formatting {
|
||||
return fixTokenKind(lastTokenInfo, n);
|
||||
}
|
||||
|
||||
function isOnToken(): boolean {
|
||||
Debug.assert(scanner !== undefined);
|
||||
function getNextToken(n: Node, expectedScanAction: ScanAction): SyntaxKind {
|
||||
const token = scanner.getToken();
|
||||
lastScanAction = ScanAction.Scan;
|
||||
switch (expectedScanAction) {
|
||||
case ScanAction.RescanGreaterThanToken:
|
||||
if (token === SyntaxKind.GreaterThanToken) {
|
||||
lastScanAction = ScanAction.RescanGreaterThanToken;
|
||||
const newToken = scanner.reScanGreaterToken();
|
||||
Debug.assert(n.kind === newToken);
|
||||
return newToken;
|
||||
}
|
||||
break;
|
||||
case ScanAction.RescanSlashToken:
|
||||
if (startsWithSlashToken(token)) {
|
||||
lastScanAction = ScanAction.RescanSlashToken;
|
||||
const newToken = scanner.reScanSlashToken();
|
||||
Debug.assert(n.kind === newToken);
|
||||
return newToken;
|
||||
}
|
||||
break;
|
||||
case ScanAction.RescanTemplateToken:
|
||||
if (token === SyntaxKind.CloseBraceToken) {
|
||||
lastScanAction = ScanAction.RescanTemplateToken;
|
||||
return scanner.reScanTemplateToken();
|
||||
}
|
||||
break;
|
||||
case ScanAction.RescanJsxIdentifier:
|
||||
lastScanAction = ScanAction.RescanJsxIdentifier;
|
||||
return scanner.scanJsxIdentifier();
|
||||
case ScanAction.RescanJsxText:
|
||||
lastScanAction = ScanAction.RescanJsxText;
|
||||
return scanner.reScanJsxToken();
|
||||
case ScanAction.Scan:
|
||||
break;
|
||||
default:
|
||||
Debug.assertNever(expectedScanAction);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
function isOnToken(): boolean {
|
||||
const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
|
||||
const startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
|
||||
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
|
||||
|
||||
@ -226,7 +226,7 @@ namespace ts.textChanges {
|
||||
Debug.fail("node is not a list element");
|
||||
return this;
|
||||
}
|
||||
const index = containingList.indexOf(node);
|
||||
const index = indexOfNode(containingList, node);
|
||||
if (index < 0) {
|
||||
return this;
|
||||
}
|
||||
@ -358,7 +358,7 @@ namespace ts.textChanges {
|
||||
Debug.fail("node is not a list element");
|
||||
return this;
|
||||
}
|
||||
const index = containingList.indexOf(after);
|
||||
const index = indexOfNode(containingList, after);
|
||||
if (index < 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -597,7 +597,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const children = list.getChildren();
|
||||
const listItemIndex = indexOf(children, node);
|
||||
const listItemIndex = indexOfNode(children, node);
|
||||
|
||||
return {
|
||||
listItemIndex,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
=== tests/cases/compiler/declarationQuotedMembers.ts ===
|
||||
export declare const mapped: { [K in 'a-b-c']: number }
|
||||
>mapped : { a-b-c: number; }
|
||||
>mapped : { "a-b-c": number; }
|
||||
>K : K
|
||||
|
||||
export const example = mapped;
|
||||
>example : { a-b-c: number; }
|
||||
>mapped : { a-b-c: number; }
|
||||
>example : { "a-b-c": number; }
|
||||
>mapped : { "a-b-c": number; }
|
||||
|
||||
|
||||
7
tests/cases/fourslash/completionsJsdocTypeTagCast.ts
Normal file
7
tests/cases/fourslash/completionsJsdocTypeTagCast.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @Filename: /a.js
|
||||
////const x = /** @type {{ s: string }} */ ({ /**/ });
|
||||
|
||||
verify.completionsAt("", ["s", "x"]);
|
||||
Loading…
x
Reference in New Issue
Block a user