Merge branch 'master' into literalTypesAlways
This commit is contained in:
commit
aeb899aecf
20
Jakefile.js
20
Jakefile.js
|
@ -126,6 +126,7 @@ var servicesSources = [
|
|||
"classifier.ts",
|
||||
"completions.ts",
|
||||
"documentHighlights.ts",
|
||||
"documentRegistry.ts",
|
||||
"findAllReferences.ts",
|
||||
"goToDefinition.ts",
|
||||
"jsDoc.ts",
|
||||
|
@ -1003,15 +1004,18 @@ function acceptBaseline(containerFolder) {
|
|||
var deleteEnding = '.delete';
|
||||
for (var i in files) {
|
||||
var filename = files[i];
|
||||
if (filename.substr(filename.length - deleteEnding.length) === deleteEnding) {
|
||||
filename = filename.substr(0, filename.length - deleteEnding.length);
|
||||
fs.unlinkSync(path.join(targetFolder, filename));
|
||||
} else {
|
||||
var target = path.join(targetFolder, filename);
|
||||
if (fs.existsSync(target)) {
|
||||
fs.unlinkSync(target);
|
||||
var fullLocalPath = path.join(sourceFolder, filename);
|
||||
if (fs.statSync(fullLocalPath).isFile()) {
|
||||
if (filename.substr(filename.length - deleteEnding.length) === deleteEnding) {
|
||||
filename = filename.substr(0, filename.length - deleteEnding.length);
|
||||
fs.unlinkSync(path.join(targetFolder, filename));
|
||||
} else {
|
||||
var target = path.join(targetFolder, filename);
|
||||
if (fs.existsSync(target)) {
|
||||
fs.unlinkSync(target);
|
||||
}
|
||||
fs.renameSync(path.join(sourceFolder, filename), target);
|
||||
}
|
||||
fs.renameSync(path.join(sourceFolder, filename), target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
lib/lib.es2015.collection.d.ts
vendored
4
lib/lib.es2015.collection.d.ts
vendored
|
@ -20,7 +20,7 @@ interface Map<K, V> {
|
|||
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): this;
|
||||
set(key: K, value: V): this;
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ interface WeakMap<K, V> {
|
|||
delete(key: K): boolean;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): this;
|
||||
set(key: K, value: V): this;
|
||||
}
|
||||
|
||||
interface WeakMapConstructor {
|
||||
|
|
|
@ -93,11 +93,16 @@ class PreferConstWalker extends Lint.RuleWalker {
|
|||
|
||||
private visitBindingPatternIdentifiers(pattern: ts.BindingPattern) {
|
||||
for (const element of pattern.elements) {
|
||||
if (element.name.kind === ts.SyntaxKind.Identifier) {
|
||||
this.markAssignment(element.name as ts.Identifier);
|
||||
if (element.kind !== ts.SyntaxKind.BindingElement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = (<ts.BindingElement>element).name;
|
||||
if (name.kind === ts.SyntaxKind.Identifier) {
|
||||
this.markAssignment(name as ts.Identifier);
|
||||
}
|
||||
else {
|
||||
this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern);
|
||||
this.visitBindingPatternIdentifiers(name as ts.BindingPattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +196,9 @@ class PreferConstWalker extends Lint.RuleWalker {
|
|||
|
||||
private collectBindingPatternIdentifiers(value: ts.VariableDeclaration, pattern: ts.BindingPattern, table: ts.MapLike<DeclarationUsages>) {
|
||||
for (const element of pattern.elements) {
|
||||
this.collectNameIdentifiers(value, element.name, table);
|
||||
if (element.kind === ts.SyntaxKind.BindingElement) {
|
||||
this.collectNameIdentifiers(value, (<ts.BindingElement>element).name, table);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1163,8 +1163,8 @@ namespace ts {
|
|||
currentFlow = finishFlowLabel(postExpressionLabel);
|
||||
}
|
||||
|
||||
function bindInitializedVariableFlow(node: VariableDeclaration | BindingElement) {
|
||||
const name = node.name;
|
||||
function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) {
|
||||
const name = !isOmittedExpression(node) ? node.name : undefined;
|
||||
if (isBindingPattern(name)) {
|
||||
for (const child of name.elements) {
|
||||
bindInitializedVariableFlow(child);
|
||||
|
|
|
@ -1043,7 +1043,7 @@ namespace ts {
|
|||
const moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent).moduleSpecifier);
|
||||
|
||||
if (moduleSymbol) {
|
||||
const exportDefaultSymbol = isShorthandAmbientModule(moduleSymbol.valueDeclaration) ?
|
||||
const exportDefaultSymbol = isShorthandAmbientModuleSymbol(moduleSymbol) ?
|
||||
moduleSymbol :
|
||||
moduleSymbol.exports["export="] ?
|
||||
getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") :
|
||||
|
@ -1119,7 +1119,7 @@ namespace ts {
|
|||
if (targetSymbol) {
|
||||
const name = specifier.propertyName || specifier.name;
|
||||
if (name.text) {
|
||||
if (isShorthandAmbientModule(moduleSymbol.valueDeclaration)) {
|
||||
if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
|
||||
return moduleSymbol;
|
||||
}
|
||||
|
||||
|
@ -2505,8 +2505,8 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function buildBindingElementDisplay(bindingElement: BindingElement, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (bindingElement.kind === SyntaxKind.OmittedExpression) {
|
||||
function buildBindingElementDisplay(bindingElement: ArrayBindingElement, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (isOmittedExpression(bindingElement)) {
|
||||
return;
|
||||
}
|
||||
Debug.assert(bindingElement.kind === SyntaxKind.BindingElement);
|
||||
|
@ -3129,7 +3129,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Return the type implied by an object binding pattern
|
||||
function getTypeFromObjectBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type {
|
||||
function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type {
|
||||
const members = createMap<Symbol>();
|
||||
let hasComputedProperties = false;
|
||||
forEach(pattern.elements, e => {
|
||||
|
@ -3160,11 +3160,12 @@ namespace ts {
|
|||
// Return the type implied by an array binding pattern
|
||||
function getTypeFromArrayBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type {
|
||||
const elements = pattern.elements;
|
||||
if (elements.length === 0 || elements[elements.length - 1].dotDotDotToken) {
|
||||
const lastElement = lastOrUndefined(elements);
|
||||
if (elements.length === 0 || (!isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) {
|
||||
return languageVersion >= ScriptTarget.ES6 ? createIterableType(anyType) : anyArrayType;
|
||||
}
|
||||
// If the pattern has at least one element, and no rest element, then it should imply a tuple type.
|
||||
const elementTypes = map(elements, e => e.kind === SyntaxKind.OmittedExpression ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors));
|
||||
const elementTypes = map(elements, e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors));
|
||||
let result = createTupleType(elementTypes);
|
||||
if (includePatternInType) {
|
||||
result = cloneTypeReference(result);
|
||||
|
@ -3182,8 +3183,8 @@ namespace ts {
|
|||
// the parameter.
|
||||
function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType?: boolean, reportErrors?: boolean): Type {
|
||||
return pattern.kind === SyntaxKind.ObjectBindingPattern
|
||||
? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors)
|
||||
: getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors);
|
||||
? getTypeFromObjectBindingPattern(<ObjectBindingPattern>pattern, includePatternInType, reportErrors)
|
||||
: getTypeFromArrayBindingPattern(<ArrayBindingPattern>pattern, includePatternInType, reportErrors);
|
||||
}
|
||||
|
||||
// Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type
|
||||
|
@ -3385,7 +3386,7 @@ namespace ts {
|
|||
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
if (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && isShorthandAmbientModule(<ModuleDeclaration>symbol.valueDeclaration)) {
|
||||
if (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && isShorthandAmbientModuleSymbol(symbol)) {
|
||||
links.type = anyType;
|
||||
}
|
||||
else {
|
||||
|
@ -8970,6 +8971,7 @@ namespace ts {
|
|||
const isParameter = getRootDeclaration(declaration).kind === SyntaxKind.Parameter;
|
||||
const declarationContainer = getControlFlowContainer(declaration);
|
||||
let flowContainer = getControlFlowContainer(node);
|
||||
const isOuterVariable = flowContainer !== declarationContainer;
|
||||
// When the control flow originates in a function expression or arrow function and we are referencing
|
||||
// a const variable or parameter from an outer function, we extend the origin of the control flow
|
||||
// analysis to include the immediately enclosing function.
|
||||
|
@ -8982,7 +8984,7 @@ namespace ts {
|
|||
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
|
||||
// declaration container are the same).
|
||||
const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isParameter ||
|
||||
flowContainer !== declarationContainer || isInAmbientContext(declaration);
|
||||
isOuterVariable || isInAmbientContext(declaration);
|
||||
const flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer);
|
||||
// A variable is considered uninitialized when it is possible to analyze the entire control flow graph
|
||||
// from declaration to use, and when the variable's declared type doesn't include undefined but the
|
||||
|
@ -12437,7 +12439,7 @@ namespace ts {
|
|||
function assignBindingElementTypes(node: VariableLikeDeclaration) {
|
||||
if (isBindingPattern(node.name)) {
|
||||
for (const element of (<BindingPattern>node.name).elements) {
|
||||
if (element.kind !== SyntaxKind.OmittedExpression) {
|
||||
if (!isOmittedExpression(element)) {
|
||||
if (element.name.kind === SyntaxKind.Identifier) {
|
||||
getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element);
|
||||
}
|
||||
|
@ -13880,7 +13882,12 @@ namespace ts {
|
|||
pattern: BindingPattern,
|
||||
predicateVariableNode: Node,
|
||||
predicateVariableName: string) {
|
||||
for (const { name } of pattern.elements) {
|
||||
for (const element of pattern.elements) {
|
||||
if (isOmittedExpression(element)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = element.name;
|
||||
if (name.kind === SyntaxKind.Identifier &&
|
||||
(<Identifier>name).text === predicateVariableName) {
|
||||
error(predicateVariableNode,
|
||||
|
@ -18356,8 +18363,8 @@ namespace ts {
|
|||
|
||||
function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
|
||||
let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression);
|
||||
if (!moduleSymbol) {
|
||||
// module not found - be conservative
|
||||
if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) {
|
||||
// If the module is not found or is shorthand, assume that it may export a value.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -19990,7 +19997,7 @@ namespace ts {
|
|||
else {
|
||||
const elements = (<BindingPattern>name).elements;
|
||||
for (const element of elements) {
|
||||
if (element.kind !== SyntaxKind.OmittedExpression) {
|
||||
if (!isOmittedExpression(element)) {
|
||||
checkGrammarNameInLetOrConstDeclarations(element.name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -554,9 +554,9 @@ const _super = (function (geti, seti) {
|
|||
|
||||
// Binding patterns
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return emitObjectBindingPattern(<BindingPattern>node);
|
||||
return emitObjectBindingPattern(<ObjectBindingPattern>node);
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return emitArrayBindingPattern(<BindingPattern>node);
|
||||
return emitArrayBindingPattern(<ArrayBindingPattern>node);
|
||||
case SyntaxKind.BindingElement:
|
||||
return emitBindingElement(<BindingElement>node);
|
||||
|
||||
|
|
|
@ -368,13 +368,13 @@ namespace ts {
|
|||
return node;
|
||||
}
|
||||
|
||||
export function createArrayBindingPattern(elements: BindingElement[], location?: TextRange) {
|
||||
export function createArrayBindingPattern(elements: ArrayBindingElement[], location?: TextRange) {
|
||||
const node = <ArrayBindingPattern>createNode(SyntaxKind.ArrayBindingPattern, location);
|
||||
node.elements = createNodeArray(elements);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateArrayBindingPattern(node: ArrayBindingPattern, elements: BindingElement[]) {
|
||||
export function updateArrayBindingPattern(node: ArrayBindingPattern, elements: ArrayBindingElement[]) {
|
||||
if (node.elements !== elements) {
|
||||
return updateNode(createArrayBindingPattern(elements, node), node);
|
||||
}
|
||||
|
|
|
@ -4815,9 +4815,9 @@ namespace ts {
|
|||
|
||||
// DECLARATIONS
|
||||
|
||||
function parseArrayBindingElement(): BindingElement {
|
||||
function parseArrayBindingElement(): ArrayBindingElement {
|
||||
if (token() === SyntaxKind.CommaToken) {
|
||||
return <BindingElement>createNode(SyntaxKind.OmittedExpression);
|
||||
return <OmittedExpression>createNode(SyntaxKind.OmittedExpression);
|
||||
}
|
||||
const node = <BindingElement>createNode(SyntaxKind.BindingElement);
|
||||
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
|
@ -4842,16 +4842,16 @@ namespace ts {
|
|||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseObjectBindingPattern(): BindingPattern {
|
||||
const node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);
|
||||
function parseObjectBindingPattern(): ObjectBindingPattern {
|
||||
const node = <ObjectBindingPattern>createNode(SyntaxKind.ObjectBindingPattern);
|
||||
parseExpected(SyntaxKind.OpenBraceToken);
|
||||
node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseArrayBindingPattern(): BindingPattern {
|
||||
const node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);
|
||||
function parseArrayBindingPattern(): ArrayBindingPattern {
|
||||
const node = <ArrayBindingPattern>createNode(SyntaxKind.ArrayBindingPattern);
|
||||
parseExpected(SyntaxKind.OpenBracketToken);
|
||||
node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
|
|
|
@ -326,12 +326,15 @@ namespace ts {
|
|||
}
|
||||
for (let i = 0; i < numElements; i++) {
|
||||
const element = elements[i];
|
||||
if (name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
if (isOmittedExpression(element)) {
|
||||
continue;
|
||||
}
|
||||
else if (name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
// Rewrite element to a declaration with an initializer that fetches property
|
||||
const propName = element.propertyName || <Identifier>element.name;
|
||||
emitBindingElement(element, createDestructuringPropertyAccess(value, propName));
|
||||
}
|
||||
else if (element.kind !== SyntaxKind.OmittedExpression) {
|
||||
else {
|
||||
if (!element.dotDotDotToken) {
|
||||
// Rewrite element to a declaration that accesses array element at index i
|
||||
emitBindingElement(element, createElementAccess(value, i));
|
||||
|
|
|
@ -1945,7 +1945,9 @@ namespace ts {
|
|||
}
|
||||
else {
|
||||
for (const element of (<BindingPattern>node).elements) {
|
||||
visit(element.name);
|
||||
if (!isOmittedExpression(element)) {
|
||||
visit(element.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2289,7 +2291,9 @@ namespace ts {
|
|||
const name = decl.name;
|
||||
if (isBindingPattern(name)) {
|
||||
for (const element of name.elements) {
|
||||
processLoopVariableDeclaration(element, loopParameters, loopOutParameters);
|
||||
if (!isOmittedExpression(element)) {
|
||||
processLoopVariableDeclaration(element, loopParameters, loopOutParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -660,7 +660,9 @@ namespace ts {
|
|||
function addExportMemberAssignmentsForBindingName(resultStatements: Statement[], name: BindingName): void {
|
||||
if (isBindingPattern(name)) {
|
||||
for (const element of name.elements) {
|
||||
addExportMemberAssignmentsForBindingName(resultStatements, element.name);
|
||||
if (!isOmittedExpression(element)) {
|
||||
addExportMemberAssignmentsForBindingName(resultStatements, element.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1368,7 +1368,11 @@ namespace ts {
|
|||
exportedFunctionDeclarations.push(createDeclarationExport(node));
|
||||
}
|
||||
|
||||
function hoistBindingElement(node: VariableDeclaration | BindingElement, isExported: boolean): void {
|
||||
function hoistBindingElement(node: VariableDeclaration | ArrayBindingElement, isExported: boolean): void {
|
||||
if (isOmittedExpression(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = node.name;
|
||||
if (isIdentifier(name)) {
|
||||
hoistVariableDeclaration(getSynthesizedClone(name));
|
||||
|
@ -1381,11 +1385,11 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function hoistExportedBindingElement(node: VariableDeclaration | BindingElement) {
|
||||
function hoistExportedBindingElement(node: VariableDeclaration | ArrayBindingElement) {
|
||||
hoistBindingElement(node, /*isExported*/ true);
|
||||
}
|
||||
|
||||
function hoistNonExportedBindingElement(node: VariableDeclaration | BindingElement) {
|
||||
function hoistNonExportedBindingElement(node: VariableDeclaration | ArrayBindingElement) {
|
||||
hoistBindingElement(node, /*isExported*/ false);
|
||||
}
|
||||
|
||||
|
|
|
@ -2187,7 +2187,7 @@ namespace ts {
|
|||
*
|
||||
* @param node The function expression node.
|
||||
*/
|
||||
function visitFunctionExpression(node: FunctionExpression) {
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
if (nodeIsMissing(node.body)) {
|
||||
return createOmittedExpression();
|
||||
}
|
||||
|
|
|
@ -688,14 +688,20 @@ namespace ts {
|
|||
}
|
||||
|
||||
export interface BindingPattern extends Node {
|
||||
elements: NodeArray<BindingElement>;
|
||||
elements: NodeArray<BindingElement | ArrayBindingElement>;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.ObjectBindingPattern)
|
||||
export interface ObjectBindingPattern extends BindingPattern { }
|
||||
export interface ObjectBindingPattern extends BindingPattern {
|
||||
elements: NodeArray<BindingElement>;
|
||||
}
|
||||
|
||||
export type ArrayBindingElement = BindingElement | OmittedExpression;
|
||||
|
||||
// @kind(SyntaxKind.ArrayBindingPattern)
|
||||
export interface ArrayBindingPattern extends BindingPattern { }
|
||||
export interface ArrayBindingPattern extends BindingPattern {
|
||||
elements: NodeArray<ArrayBindingElement>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Several node kinds share function-like features such as a signature,
|
||||
|
@ -868,7 +874,9 @@ namespace ts {
|
|||
}
|
||||
|
||||
// @kind(SyntaxKind.OmittedExpression)
|
||||
export interface OmittedExpression extends Expression { }
|
||||
export interface OmittedExpression extends Expression {
|
||||
_omittedExpressionBrand: any;
|
||||
}
|
||||
|
||||
// Represents an expression that is elided as part of a transformation to emit comments on a
|
||||
// not-emitted node. The 'expression' property of a NotEmittedExpression should be emitted.
|
||||
|
|
|
@ -414,7 +414,11 @@ namespace ts {
|
|||
((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(<ModuleDeclaration>node));
|
||||
}
|
||||
|
||||
export function isShorthandAmbientModule(node: Node): boolean {
|
||||
export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean {
|
||||
return isShorthandAmbientModule(moduleSymbol.valueDeclaration);
|
||||
}
|
||||
|
||||
function isShorthandAmbientModule(node: Node): boolean {
|
||||
// The only kind of module that can be missing a body is a shorthand ambient module.
|
||||
return node.kind === SyntaxKind.ModuleDeclaration && (!(<ModuleDeclaration>node).body);
|
||||
}
|
||||
|
@ -3701,6 +3705,12 @@ namespace ts {
|
|||
return node.kind === SyntaxKind.BindingElement;
|
||||
}
|
||||
|
||||
export function isArrayBindingElement(node: Node): node is ArrayBindingElement {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.BindingElement
|
||||
|| kind === SyntaxKind.OmittedExpression;
|
||||
}
|
||||
|
||||
// Expression
|
||||
|
||||
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
|
||||
|
@ -3817,6 +3827,10 @@ namespace ts {
|
|||
|| isPartiallyEmittedExpression(node);
|
||||
}
|
||||
|
||||
export function isOmittedExpression(node: Node): node is OmittedExpression {
|
||||
return node.kind === SyntaxKind.OmittedExpression;
|
||||
}
|
||||
|
||||
// Misc
|
||||
|
||||
export function isTemplateSpan(node: Node): node is TemplateSpan {
|
||||
|
|
|
@ -757,7 +757,7 @@ namespace ts {
|
|||
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return updateArrayBindingPattern(<ArrayBindingPattern>node,
|
||||
visitNodes((<ArrayBindingPattern>node).elements, visitor, isBindingElement));
|
||||
visitNodes((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
return updateBindingElement(<BindingElement>node,
|
||||
|
|
|
@ -954,26 +954,20 @@ namespace FourSlash {
|
|||
assert.equal(actual, expected);
|
||||
}
|
||||
|
||||
public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) {
|
||||
public verifyQuickInfoString(negative: boolean, expectedText: string, expectedDocumentation?: string) {
|
||||
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
const actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : "";
|
||||
const actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : "";
|
||||
|
||||
if (negative) {
|
||||
if (expectedText !== undefined) {
|
||||
assert.notEqual(actualQuickInfoText, expectedText, this.messageAtLastKnownMarker("quick info text"));
|
||||
}
|
||||
// TODO: should be '==='?
|
||||
if (expectedDocumentation != undefined) {
|
||||
assert.notEqual(actualQuickInfoText, expectedText, this.messageAtLastKnownMarker("quick info text"));
|
||||
if (expectedDocumentation !== undefined) {
|
||||
assert.notEqual(actualQuickInfoDocumentation, expectedDocumentation, this.messageAtLastKnownMarker("quick info doc comment"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (expectedText !== undefined) {
|
||||
assert.equal(actualQuickInfoText, expectedText, this.messageAtLastKnownMarker("quick info text"));
|
||||
}
|
||||
// TODO: should be '==='?
|
||||
if (expectedDocumentation != undefined) {
|
||||
assert.equal(actualQuickInfoText, expectedText, this.messageAtLastKnownMarker("quick info text"));
|
||||
if (expectedDocumentation !== undefined) {
|
||||
assert.equal(actualQuickInfoDocumentation, expectedDocumentation, this.assertionMessageAtLastKnownMarker("quick info doc"));
|
||||
}
|
||||
}
|
||||
|
@ -2969,7 +2963,7 @@ namespace FourSlashInterface {
|
|||
this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ false);
|
||||
}
|
||||
|
||||
public quickInfoIs(expectedText?: string, expectedDocumentation?: string) {
|
||||
public quickInfoIs(expectedText: string, expectedDocumentation?: string) {
|
||||
this.state.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation);
|
||||
}
|
||||
|
||||
|
|
|
@ -232,8 +232,8 @@ namespace Harness.LanguageService {
|
|||
}
|
||||
getHost() { return this.host; }
|
||||
getLanguageService(): ts.LanguageService { return ts.createLanguageService(this.host); }
|
||||
getClassifier(): ts.Classifier { return ts.Classifier.createClassifier(); }
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.PreProcess.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJavaScriptFileExtension(fileName)); }
|
||||
getClassifier(): ts.Classifier { return ts.createClassifier(); }
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJavaScriptFileExtension(fileName)); }
|
||||
}
|
||||
|
||||
/// Shim adapter
|
||||
|
@ -258,7 +258,7 @@ namespace Harness.LanguageService {
|
|||
};
|
||||
this.getModuleResolutionsForFile = (fileName) => {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
const preprocessInfo = ts.PreProcess.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
|
||||
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
|
||||
const imports = ts.createMap<string>();
|
||||
for (const module of preprocessInfo.importedFiles) {
|
||||
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
|
||||
|
@ -271,7 +271,7 @@ namespace Harness.LanguageService {
|
|||
this.getTypeReferenceDirectiveResolutionsForFile = (fileName) => {
|
||||
const scriptInfo = this.getScriptInfo(fileName);
|
||||
if (scriptInfo) {
|
||||
const preprocessInfo = ts.PreProcess.preProcessFile(scriptInfo.content, /*readImportFiles*/ false);
|
||||
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ false);
|
||||
const resolutions = ts.createMap<ts.ResolvedTypeReferenceDirective>();
|
||||
const settings = this.nativeHost.getCompilationSettings();
|
||||
for (const typeReferenceDirective of preprocessInfo.typeReferenceDirectives) {
|
||||
|
@ -408,6 +408,9 @@ namespace Harness.LanguageService {
|
|||
getCompletionEntryDetails(fileName: string, position: number, entryName: string): ts.CompletionEntryDetails {
|
||||
return unwrapJSONCallResult(this.shim.getCompletionEntryDetails(fileName, position, entryName));
|
||||
}
|
||||
getCompletionEntrySymbol(fileName: string, position: number, entryName: string): ts.Symbol {
|
||||
throw new Error("getCompletionEntrySymbol not implemented across the shim layer.");
|
||||
}
|
||||
getQuickInfoAtPosition(fileName: string, position: number): ts.QuickInfo {
|
||||
return unwrapJSONCallResult(this.shim.getQuickInfoAtPosition(fileName, position));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
describe("PreProcessFile:", function () {
|
||||
function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void {
|
||||
const resultPreProcess = ts.PreProcess.preProcessFile(sourceText, readImportFile, detectJavaScriptImports);
|
||||
const resultPreProcess = ts.preProcessFile(sourceText, readImportFile, detectJavaScriptImports);
|
||||
|
||||
assert.equal(resultPreProcess.isLibFile, expectedPreProcess.isLibFile, "Pre-processed file has different value for isLibFile. Expected: " + expectedPreProcess.isLibFile + ". Actual: " + resultPreProcess.isLibFile);
|
||||
|
||||
|
|
|
@ -246,6 +246,10 @@ namespace ts.server {
|
|||
return response.body[0];
|
||||
}
|
||||
|
||||
getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getNavigateToItems(searchValue: string): NavigateToItem[] {
|
||||
const args: protocol.NavtoRequestArgs = {
|
||||
searchValue,
|
||||
|
|
|
@ -1566,7 +1566,7 @@ namespace ts.server {
|
|||
this.setCompilerOptions(defaultOpts);
|
||||
}
|
||||
this.languageService = ts.createLanguageService(this.host, this.documentRegistry);
|
||||
this.classifier = ts.Classifier.createClassifier();
|
||||
this.classifier = ts.createClassifier();
|
||||
}
|
||||
|
||||
setCompilerOptions(opt: ts.CompilerOptions) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* @internal */
|
||||
namespace ts.Classifier {
|
||||
namespace ts {
|
||||
/// Classifier
|
||||
export function createClassifier(): Classifier {
|
||||
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
|
||||
|
@ -462,6 +461,7 @@ namespace ts.Classifier {
|
|||
};
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map<string>, span: TextSpan): ClassifiedSpan[] {
|
||||
return convertClassifications(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span));
|
||||
}
|
||||
|
@ -486,6 +486,7 @@ namespace ts.Classifier {
|
|||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map<string>, span: TextSpan): Classifications {
|
||||
const result: number[] = [];
|
||||
processNode(sourceFile);
|
||||
|
@ -614,10 +615,12 @@ namespace ts.Classifier {
|
|||
return result;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): ClassifiedSpan[] {
|
||||
return convertClassifications(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span));
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getEncodedSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): Classifications {
|
||||
const spanStart = span.start;
|
||||
const spanLength = span.length;
|
||||
|
|
|
@ -736,6 +736,22 @@ namespace ts.Completions {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
export function getCompletionEntrySymbol(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): Symbol {
|
||||
// Compute all the completion symbols again.
|
||||
const completionData = getCompletionData(typeChecker, log, sourceFile, position);
|
||||
if (completionData) {
|
||||
const { symbols, location } = completionData;
|
||||
|
||||
// Find the symbol with the matching entry name.
|
||||
// We don't need to perform character checks here because we're only comparing the
|
||||
// name against 'entryName' (which is known to be good), not building a new
|
||||
// completion entry.
|
||||
return forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(typeChecker, s, compilerOptions.target, /*performCharacterChecks*/ false, location) === entryName ? s : undefined);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number) {
|
||||
const isJavaScriptFile = isSourceFileJavaScript(sourceFile);
|
||||
|
||||
|
@ -1192,7 +1208,7 @@ namespace ts.Completions {
|
|||
}
|
||||
if (canGetType) {
|
||||
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||
existingMembers = (<BindingPattern>objectLikeContainer).elements;
|
||||
existingMembers = (<ObjectBindingPattern>objectLikeContainer).elements;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
240
src/services/documentRegistry.ts
Normal file
240
src/services/documentRegistry.ts
Normal file
|
@ -0,0 +1,240 @@
|
|||
namespace ts {
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
* multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
|
||||
* of files in the context.
|
||||
* SourceFile objects account for most of the memory usage by the language service. Sharing
|
||||
* the same DocumentRegistry instance between different instances of LanguageService allow
|
||||
* for more efficient memory utilization since all projects will share at least the library
|
||||
* file (lib.d.ts).
|
||||
*
|
||||
* A more advanced use of the document registry is to serialize sourceFile objects to disk
|
||||
* and re-hydrate them when needed.
|
||||
*
|
||||
* To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it
|
||||
* to all subsequent createLanguageService calls.
|
||||
*/
|
||||
export interface DocumentRegistry {
|
||||
/**
|
||||
* Request a stored SourceFile with a given fileName and compilationSettings.
|
||||
* The first call to acquire will call createLanguageServiceSourceFile to generate
|
||||
* the SourceFile if was not found in the registry.
|
||||
*
|
||||
* @param fileName The name of the file requested
|
||||
* @param compilationSettings Some compilation settings like target affects the
|
||||
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
|
||||
* multiple copies of the same file for different compilation settings.
|
||||
* @parm scriptSnapshot Text of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
* @parm version Current version of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
*/
|
||||
acquireDocument(
|
||||
fileName: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
acquireDocumentWithKey(
|
||||
fileName: string,
|
||||
path: Path,
|
||||
compilationSettings: CompilerOptions,
|
||||
key: DocumentRegistryBucketKey,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
/**
|
||||
* Request an updated version of an already existing SourceFile with a given fileName
|
||||
* and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile
|
||||
* to get an updated SourceFile.
|
||||
*
|
||||
* @param fileName The name of the file requested
|
||||
* @param compilationSettings Some compilation settings like target affects the
|
||||
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
|
||||
* multiple copies of the same file for different compilation settings.
|
||||
* @param scriptSnapshot Text of the file.
|
||||
* @param version Current version of the file.
|
||||
*/
|
||||
updateDocument(
|
||||
fileName: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
updateDocumentWithKey(
|
||||
fileName: string,
|
||||
path: Path,
|
||||
compilationSettings: CompilerOptions,
|
||||
key: DocumentRegistryBucketKey,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey;
|
||||
/**
|
||||
* Informs the DocumentRegistry that a file is not needed any longer.
|
||||
*
|
||||
* Note: It is not allowed to call release on a SourceFile that was not acquired from
|
||||
* this registry originally.
|
||||
*
|
||||
* @param fileName The name of the file to be released
|
||||
* @param compilationSettings The compilation settings used to acquire the file
|
||||
*/
|
||||
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
|
||||
|
||||
releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void;
|
||||
|
||||
reportStats(): string;
|
||||
}
|
||||
|
||||
export type DocumentRegistryBucketKey = string & { __bucketKey: any };
|
||||
|
||||
interface DocumentRegistryEntry {
|
||||
sourceFile: SourceFile;
|
||||
|
||||
// The number of language services that this source file is referenced in. When no more
|
||||
// language services are referencing the file, then the file can be removed from the
|
||||
// registry.
|
||||
languageServiceRefCount: number;
|
||||
owners: string[];
|
||||
}
|
||||
|
||||
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry {
|
||||
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
|
||||
// for those settings.
|
||||
const buckets = createMap<FileMap<DocumentRegistryEntry>>();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
|
||||
function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey {
|
||||
return <DocumentRegistryBucketKey>`_${settings.target}|${settings.module}|${settings.noResolve}|${settings.jsx}|${settings.allowJs}|${settings.baseUrl}|${JSON.stringify(settings.typeRoots)}|${JSON.stringify(settings.rootDirs)}|${JSON.stringify(settings.paths)}`;
|
||||
}
|
||||
|
||||
function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): FileMap<DocumentRegistryEntry> {
|
||||
let bucket = buckets[key];
|
||||
if (!bucket && createIfMissing) {
|
||||
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>();
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
|
||||
function reportStats() {
|
||||
const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => {
|
||||
const entries = buckets[name];
|
||||
const sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
|
||||
entries.forEachValue((key, entry) => {
|
||||
sourceFiles.push({
|
||||
name: key,
|
||||
refCount: entry.languageServiceRefCount,
|
||||
references: entry.owners.slice(0)
|
||||
});
|
||||
});
|
||||
sourceFiles.sort((x, y) => y.refCount - x.refCount);
|
||||
return {
|
||||
bucket: name,
|
||||
sourceFiles
|
||||
};
|
||||
});
|
||||
return JSON.stringify(bucketInfoArray, undefined, 2);
|
||||
}
|
||||
|
||||
function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const key = getKeyForCompilationSettings(compilationSettings);
|
||||
return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
|
||||
}
|
||||
|
||||
function acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind);
|
||||
}
|
||||
|
||||
function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const key = getKeyForCompilationSettings(compilationSettings);
|
||||
return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
|
||||
}
|
||||
|
||||
function updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind);
|
||||
}
|
||||
|
||||
function acquireOrUpdateDocument(
|
||||
fileName: string,
|
||||
path: Path,
|
||||
compilationSettings: CompilerOptions,
|
||||
key: DocumentRegistryBucketKey,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
acquiring: boolean,
|
||||
scriptKind?: ScriptKind): SourceFile {
|
||||
|
||||
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
|
||||
let entry = bucket.get(path);
|
||||
if (!entry) {
|
||||
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
|
||||
|
||||
// Have never seen this file with these settings. Create a new source file for it.
|
||||
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind);
|
||||
|
||||
entry = {
|
||||
sourceFile: sourceFile,
|
||||
languageServiceRefCount: 0,
|
||||
owners: []
|
||||
};
|
||||
bucket.set(path, entry);
|
||||
}
|
||||
else {
|
||||
// We have an entry for this file. However, it may be for a different version of
|
||||
// the script snapshot. If so, update it appropriately. Otherwise, we can just
|
||||
// return it as is.
|
||||
if (entry.sourceFile.version !== version) {
|
||||
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
|
||||
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
|
||||
}
|
||||
}
|
||||
|
||||
// If we're acquiring, then this is the first time this LS is asking for this document.
|
||||
// Increase our ref count so we know there's another LS using the document. If we're
|
||||
// not acquiring, then that means the LS is 'updating' the file instead, and that means
|
||||
// it has already acquired the document previously. As such, we do not need to increase
|
||||
// the ref count.
|
||||
if (acquiring) {
|
||||
entry.languageServiceRefCount++;
|
||||
}
|
||||
|
||||
return entry.sourceFile;
|
||||
}
|
||||
|
||||
function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const key = getKeyForCompilationSettings(compilationSettings);
|
||||
return releaseDocumentWithKey(path, key);
|
||||
}
|
||||
|
||||
function releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void {
|
||||
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/false);
|
||||
Debug.assert(bucket !== undefined);
|
||||
|
||||
const entry = bucket.get(path);
|
||||
entry.languageServiceRefCount--;
|
||||
|
||||
Debug.assert(entry.languageServiceRefCount >= 0);
|
||||
if (entry.languageServiceRefCount === 0) {
|
||||
bucket.remove(path);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
acquireDocument,
|
||||
acquireDocumentWithKey,
|
||||
updateDocument,
|
||||
updateDocumentWithKey,
|
||||
releaseDocument,
|
||||
releaseDocumentWithKey,
|
||||
reportStats,
|
||||
getKeyForCompilationSettings
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
/* @internal */
|
||||
namespace ts.PreProcess {
|
||||
namespace ts {
|
||||
export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo {
|
||||
const referencedFiles: FileReference[] = [];
|
||||
const typeReferenceDirectives: FileReference[] = [];
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
/// <reference path='classifier.ts' />
|
||||
/// <reference path='completions.ts' />
|
||||
/// <reference path='documentHighlights.ts' />
|
||||
/// <reference path='documentRegistry.ts' />
|
||||
/// <reference path='findAllReferences.ts' />
|
||||
/// <reference path='goToDefinition.ts' />
|
||||
/// <reference path='jsDoc.ts' />
|
||||
|
@ -668,16 +669,6 @@ namespace ts {
|
|||
scriptKind: ScriptKind;
|
||||
}
|
||||
|
||||
interface DocumentRegistryEntry {
|
||||
sourceFile: SourceFile;
|
||||
|
||||
// The number of language services that this source file is referenced in. When no more
|
||||
// language services are referencing the file, then the file can be removed from the
|
||||
// registry.
|
||||
languageServiceRefCount: number;
|
||||
owners: string[];
|
||||
}
|
||||
|
||||
export interface DisplayPartsSymbolWriter extends SymbolWriter {
|
||||
displayParts(): SymbolDisplayPart[];
|
||||
}
|
||||
|
@ -899,142 +890,6 @@ namespace ts {
|
|||
return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind);
|
||||
}
|
||||
|
||||
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry {
|
||||
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
|
||||
// for those settings.
|
||||
const buckets = createMap<FileMap<DocumentRegistryEntry>>();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
|
||||
function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey {
|
||||
return <DocumentRegistryBucketKey>`_${settings.target}|${settings.module}|${settings.noResolve}|${settings.jsx}|${settings.allowJs}|${settings.baseUrl}|${JSON.stringify(settings.typeRoots)}|${JSON.stringify(settings.rootDirs)}|${JSON.stringify(settings.paths)}`;
|
||||
}
|
||||
|
||||
function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): FileMap<DocumentRegistryEntry> {
|
||||
let bucket = buckets[key];
|
||||
if (!bucket && createIfMissing) {
|
||||
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>();
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
|
||||
function reportStats() {
|
||||
const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => {
|
||||
const entries = buckets[name];
|
||||
const sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
|
||||
entries.forEachValue((key, entry) => {
|
||||
sourceFiles.push({
|
||||
name: key,
|
||||
refCount: entry.languageServiceRefCount,
|
||||
references: entry.owners.slice(0)
|
||||
});
|
||||
});
|
||||
sourceFiles.sort((x, y) => y.refCount - x.refCount);
|
||||
return {
|
||||
bucket: name,
|
||||
sourceFiles
|
||||
};
|
||||
});
|
||||
return JSON.stringify(bucketInfoArray, undefined, 2);
|
||||
}
|
||||
|
||||
function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const key = getKeyForCompilationSettings(compilationSettings);
|
||||
return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
|
||||
}
|
||||
|
||||
function acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind);
|
||||
}
|
||||
|
||||
function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const key = getKeyForCompilationSettings(compilationSettings);
|
||||
return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
|
||||
}
|
||||
|
||||
function updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile {
|
||||
return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind);
|
||||
}
|
||||
|
||||
function acquireOrUpdateDocument(
|
||||
fileName: string,
|
||||
path: Path,
|
||||
compilationSettings: CompilerOptions,
|
||||
key: DocumentRegistryBucketKey,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
acquiring: boolean,
|
||||
scriptKind?: ScriptKind): SourceFile {
|
||||
|
||||
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
|
||||
let entry = bucket.get(path);
|
||||
if (!entry) {
|
||||
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
|
||||
|
||||
// Have never seen this file with these settings. Create a new source file for it.
|
||||
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind);
|
||||
|
||||
entry = {
|
||||
sourceFile: sourceFile,
|
||||
languageServiceRefCount: 0,
|
||||
owners: []
|
||||
};
|
||||
bucket.set(path, entry);
|
||||
}
|
||||
else {
|
||||
// We have an entry for this file. However, it may be for a different version of
|
||||
// the script snapshot. If so, update it appropriately. Otherwise, we can just
|
||||
// return it as is.
|
||||
if (entry.sourceFile.version !== version) {
|
||||
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
|
||||
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
|
||||
}
|
||||
}
|
||||
|
||||
// If we're acquiring, then this is the first time this LS is asking for this document.
|
||||
// Increase our ref count so we know there's another LS using the document. If we're
|
||||
// not acquiring, then that means the LS is 'updating' the file instead, and that means
|
||||
// it has already acquired the document previously. As such, we do not need to increase
|
||||
// the ref count.
|
||||
if (acquiring) {
|
||||
entry.languageServiceRefCount++;
|
||||
}
|
||||
|
||||
return entry.sourceFile;
|
||||
}
|
||||
|
||||
function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const key = getKeyForCompilationSettings(compilationSettings);
|
||||
return releaseDocumentWithKey(path, key);
|
||||
}
|
||||
|
||||
function releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void {
|
||||
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/false);
|
||||
Debug.assert(bucket !== undefined);
|
||||
|
||||
const entry = bucket.get(path);
|
||||
entry.languageServiceRefCount--;
|
||||
|
||||
Debug.assert(entry.languageServiceRefCount >= 0);
|
||||
if (entry.languageServiceRefCount === 0) {
|
||||
bucket.remove(path);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
acquireDocument,
|
||||
acquireDocumentWithKey,
|
||||
updateDocument,
|
||||
updateDocumentWithKey,
|
||||
releaseDocument,
|
||||
releaseDocumentWithKey,
|
||||
reportStats,
|
||||
getKeyForCompilationSettings
|
||||
};
|
||||
}
|
||||
|
||||
class CancellationTokenObject implements CancellationToken {
|
||||
constructor(private cancellationToken: HostCancellationToken) {
|
||||
}
|
||||
|
@ -1351,6 +1206,11 @@ namespace ts {
|
|||
return Completions.getCompletionEntryDetails(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName);
|
||||
}
|
||||
|
||||
function getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol {
|
||||
synchronizeHostData();
|
||||
return Completions.getCompletionEntrySymbol(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName);
|
||||
}
|
||||
|
||||
function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
|
||||
synchronizeHostData();
|
||||
|
||||
|
@ -1601,22 +1461,22 @@ namespace ts {
|
|||
|
||||
function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
|
||||
synchronizeHostData();
|
||||
return Classifier.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
|
||||
return ts.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
|
||||
}
|
||||
|
||||
function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications {
|
||||
synchronizeHostData();
|
||||
return Classifier.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
|
||||
return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
|
||||
}
|
||||
|
||||
function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
|
||||
// doesn't use compiler - no need to synchronize with host
|
||||
return Classifier.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span);
|
||||
return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span);
|
||||
}
|
||||
|
||||
function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications {
|
||||
// doesn't use compiler - no need to synchronize with host
|
||||
return Classifier.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span);
|
||||
return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span);
|
||||
}
|
||||
|
||||
function getOutliningSpans(fileName: string): OutliningSpan[] {
|
||||
|
@ -1913,6 +1773,7 @@ namespace ts {
|
|||
getEncodedSemanticClassifications,
|
||||
getCompletionsAtPosition,
|
||||
getCompletionEntryDetails,
|
||||
getCompletionEntrySymbol,
|
||||
getSignatureHelpItems,
|
||||
getQuickInfoAtPosition,
|
||||
getDefinitionAtPosition,
|
||||
|
|
|
@ -986,7 +986,7 @@ namespace ts {
|
|||
|
||||
constructor(factory: ShimFactory, private logger: Logger) {
|
||||
super(factory);
|
||||
this.classifier = Classifier.createClassifier();
|
||||
this.classifier = createClassifier();
|
||||
}
|
||||
|
||||
public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string {
|
||||
|
@ -1047,7 +1047,7 @@ namespace ts {
|
|||
`getPreProcessedFileInfo('${fileName}')`,
|
||||
() => {
|
||||
// for now treat files as JavaScript
|
||||
const result = PreProcess.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
|
||||
const result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
|
||||
return {
|
||||
referencedFiles: this.convertFileReferences(result.referencedFiles),
|
||||
importedFiles: this.convertFileReferences(result.importedFiles),
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"classifier.ts",
|
||||
"completions.ts",
|
||||
"documentHighlights.ts",
|
||||
"documentRegistry.ts",
|
||||
"findAllReferences.ts",
|
||||
"goToDefinition.ts",
|
||||
"jsDoc.ts",
|
||||
|
|
|
@ -194,6 +194,7 @@ namespace ts {
|
|||
|
||||
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo;
|
||||
getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails;
|
||||
getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol;
|
||||
|
||||
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo;
|
||||
|
||||
|
@ -575,99 +576,6 @@ namespace ts {
|
|||
getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
* multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
|
||||
* of files in the context.
|
||||
* SourceFile objects account for most of the memory usage by the language service. Sharing
|
||||
* the same DocumentRegistry instance between different instances of LanguageService allow
|
||||
* for more efficient memory utilization since all projects will share at least the library
|
||||
* file (lib.d.ts).
|
||||
*
|
||||
* A more advanced use of the document registry is to serialize sourceFile objects to disk
|
||||
* and re-hydrate them when needed.
|
||||
*
|
||||
* To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it
|
||||
* to all subsequent createLanguageService calls.
|
||||
*/
|
||||
export interface DocumentRegistry {
|
||||
/**
|
||||
* Request a stored SourceFile with a given fileName and compilationSettings.
|
||||
* The first call to acquire will call createLanguageServiceSourceFile to generate
|
||||
* the SourceFile if was not found in the registry.
|
||||
*
|
||||
* @param fileName The name of the file requested
|
||||
* @param compilationSettings Some compilation settings like target affects the
|
||||
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
|
||||
* multiple copies of the same file for different compilation settings.
|
||||
* @parm scriptSnapshot Text of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
* @parm version Current version of the file. Only used if the file was not found
|
||||
* in the registry and a new one was created.
|
||||
*/
|
||||
acquireDocument(
|
||||
fileName: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
acquireDocumentWithKey(
|
||||
fileName: string,
|
||||
path: Path,
|
||||
compilationSettings: CompilerOptions,
|
||||
key: DocumentRegistryBucketKey,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
/**
|
||||
* Request an updated version of an already existing SourceFile with a given fileName
|
||||
* and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile
|
||||
* to get an updated SourceFile.
|
||||
*
|
||||
* @param fileName The name of the file requested
|
||||
* @param compilationSettings Some compilation settings like target affects the
|
||||
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
|
||||
* multiple copies of the same file for different compilation settings.
|
||||
* @param scriptSnapshot Text of the file.
|
||||
* @param version Current version of the file.
|
||||
*/
|
||||
updateDocument(
|
||||
fileName: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
updateDocumentWithKey(
|
||||
fileName: string,
|
||||
path: Path,
|
||||
compilationSettings: CompilerOptions,
|
||||
key: DocumentRegistryBucketKey,
|
||||
scriptSnapshot: IScriptSnapshot,
|
||||
version: string,
|
||||
scriptKind?: ScriptKind): SourceFile;
|
||||
|
||||
getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey;
|
||||
/**
|
||||
* Informs the DocumentRegistry that a file is not needed any longer.
|
||||
*
|
||||
* Note: It is not allowed to call release on a SourceFile that was not acquired from
|
||||
* this registry originally.
|
||||
*
|
||||
* @param fileName The name of the file to be released
|
||||
* @param compilationSettings The compilation settings used to acquire the file
|
||||
*/
|
||||
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
|
||||
|
||||
releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void;
|
||||
|
||||
reportStats(): string;
|
||||
}
|
||||
|
||||
export type DocumentRegistryBucketKey = string & { __bucketKey: any };
|
||||
|
||||
// TODO: move these to enums
|
||||
export namespace ScriptElementKind {
|
||||
export const unknown = "";
|
||||
|
|
|
@ -22,6 +22,10 @@ var jquery_1 = require("jquery");
|
|||
exports.x = jquery_1.x;
|
||||
//// [reExportAll.js]
|
||||
"use strict";
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}
|
||||
__export(require("jquery"));
|
||||
//// [reExportUser.js]
|
||||
"use strict";
|
||||
var reExportX_1 = require("./reExportX");
|
||||
|
|
26
tests/baselines/reference/controlFlowOuterVariable.js
Normal file
26
tests/baselines/reference/controlFlowOuterVariable.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
//// [controlFlowOuterVariable.ts]
|
||||
|
||||
// Repros from #10641
|
||||
|
||||
const CONFIG = {
|
||||
foo: '',
|
||||
setFoo: function(foo: string) {
|
||||
CONFIG.foo = foo;
|
||||
}
|
||||
};
|
||||
|
||||
const helper = function<T>(t: T[]) {
|
||||
helper(t.slice(1));
|
||||
}
|
||||
|
||||
//// [controlFlowOuterVariable.js]
|
||||
// Repros from #10641
|
||||
var CONFIG = {
|
||||
foo: '',
|
||||
setFoo: function (foo) {
|
||||
CONFIG.foo = foo;
|
||||
}
|
||||
};
|
||||
var helper = function (t) {
|
||||
helper(t.slice(1));
|
||||
};
|
34
tests/baselines/reference/controlFlowOuterVariable.symbols
Normal file
34
tests/baselines/reference/controlFlowOuterVariable.symbols
Normal file
|
@ -0,0 +1,34 @@
|
|||
=== tests/cases/compiler/controlFlowOuterVariable.ts ===
|
||||
|
||||
// Repros from #10641
|
||||
|
||||
const CONFIG = {
|
||||
>CONFIG : Symbol(CONFIG, Decl(controlFlowOuterVariable.ts, 3, 5))
|
||||
|
||||
foo: '',
|
||||
>foo : Symbol(foo, Decl(controlFlowOuterVariable.ts, 3, 16))
|
||||
|
||||
setFoo: function(foo: string) {
|
||||
>setFoo : Symbol(setFoo, Decl(controlFlowOuterVariable.ts, 4, 12))
|
||||
>foo : Symbol(foo, Decl(controlFlowOuterVariable.ts, 5, 21))
|
||||
|
||||
CONFIG.foo = foo;
|
||||
>CONFIG.foo : Symbol(foo, Decl(controlFlowOuterVariable.ts, 3, 16))
|
||||
>CONFIG : Symbol(CONFIG, Decl(controlFlowOuterVariable.ts, 3, 5))
|
||||
>foo : Symbol(foo, Decl(controlFlowOuterVariable.ts, 3, 16))
|
||||
>foo : Symbol(foo, Decl(controlFlowOuterVariable.ts, 5, 21))
|
||||
}
|
||||
};
|
||||
|
||||
const helper = function<T>(t: T[]) {
|
||||
>helper : Symbol(helper, Decl(controlFlowOuterVariable.ts, 10, 5))
|
||||
>T : Symbol(T, Decl(controlFlowOuterVariable.ts, 10, 24))
|
||||
>t : Symbol(t, Decl(controlFlowOuterVariable.ts, 10, 27))
|
||||
>T : Symbol(T, Decl(controlFlowOuterVariable.ts, 10, 24))
|
||||
|
||||
helper(t.slice(1));
|
||||
>helper : Symbol(helper, Decl(controlFlowOuterVariable.ts, 10, 5))
|
||||
>t.slice : Symbol(Array.slice, Decl(lib.d.ts, --, --))
|
||||
>t : Symbol(t, Decl(controlFlowOuterVariable.ts, 10, 27))
|
||||
>slice : Symbol(Array.slice, Decl(lib.d.ts, --, --))
|
||||
}
|
42
tests/baselines/reference/controlFlowOuterVariable.types
Normal file
42
tests/baselines/reference/controlFlowOuterVariable.types
Normal file
|
@ -0,0 +1,42 @@
|
|||
=== tests/cases/compiler/controlFlowOuterVariable.ts ===
|
||||
|
||||
// Repros from #10641
|
||||
|
||||
const CONFIG = {
|
||||
>CONFIG : { foo: string; setFoo: (foo: string) => void; }
|
||||
>{ foo: '', setFoo: function(foo: string) { CONFIG.foo = foo; }} : { foo: string; setFoo: (foo: string) => void; }
|
||||
|
||||
foo: '',
|
||||
>foo : string
|
||||
>'' : string
|
||||
|
||||
setFoo: function(foo: string) {
|
||||
>setFoo : (foo: string) => void
|
||||
>function(foo: string) { CONFIG.foo = foo; } : (foo: string) => void
|
||||
>foo : string
|
||||
|
||||
CONFIG.foo = foo;
|
||||
>CONFIG.foo = foo : string
|
||||
>CONFIG.foo : string
|
||||
>CONFIG : { foo: string; setFoo: (foo: string) => void; }
|
||||
>foo : string
|
||||
>foo : string
|
||||
}
|
||||
};
|
||||
|
||||
const helper = function<T>(t: T[]) {
|
||||
>helper : <T>(t: T[]) => void
|
||||
>function<T>(t: T[]) { helper(t.slice(1));} : <T>(t: T[]) => void
|
||||
>T : T
|
||||
>t : T[]
|
||||
>T : T
|
||||
|
||||
helper(t.slice(1));
|
||||
>helper(t.slice(1)) : void
|
||||
>helper : <T>(t: T[]) => void
|
||||
>t.slice(1) : T[]
|
||||
>t.slice : (start?: number | undefined, end?: number | undefined) => T[]
|
||||
>t : T[]
|
||||
>slice : (start?: number | undefined, end?: number | undefined) => T[]
|
||||
>1 : number
|
||||
}
|
11
tests/baselines/reference/exportArrayBindingPattern.js
Normal file
11
tests/baselines/reference/exportArrayBindingPattern.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
//// [exportArrayBindingPattern.ts]
|
||||
// issue: https://github.com/Microsoft/TypeScript/issues/10778
|
||||
const [a, , b] = [1, 2, 3];
|
||||
export { a, b };
|
||||
|
||||
//// [exportArrayBindingPattern.js]
|
||||
"use strict";
|
||||
// issue: https://github.com/Microsoft/TypeScript/issues/10778
|
||||
var _a = [1, 2, 3], a = _a[0], b = _a[2];
|
||||
exports.a = a;
|
||||
exports.b = b;
|
10
tests/baselines/reference/exportArrayBindingPattern.symbols
Normal file
10
tests/baselines/reference/exportArrayBindingPattern.symbols
Normal file
|
@ -0,0 +1,10 @@
|
|||
=== tests/cases/compiler/exportArrayBindingPattern.ts ===
|
||||
// issue: https://github.com/Microsoft/TypeScript/issues/10778
|
||||
const [a, , b] = [1, 2, 3];
|
||||
>a : Symbol(a, Decl(exportArrayBindingPattern.ts, 1, 7))
|
||||
>b : Symbol(b, Decl(exportArrayBindingPattern.ts, 1, 11))
|
||||
|
||||
export { a, b };
|
||||
>a : Symbol(a, Decl(exportArrayBindingPattern.ts, 2, 8))
|
||||
>b : Symbol(b, Decl(exportArrayBindingPattern.ts, 2, 11))
|
||||
|
15
tests/baselines/reference/exportArrayBindingPattern.types
Normal file
15
tests/baselines/reference/exportArrayBindingPattern.types
Normal file
|
@ -0,0 +1,15 @@
|
|||
=== tests/cases/compiler/exportArrayBindingPattern.ts ===
|
||||
// issue: https://github.com/Microsoft/TypeScript/issues/10778
|
||||
const [a, , b] = [1, 2, 3];
|
||||
>a : number
|
||||
> : undefined
|
||||
>b : number
|
||||
>[1, 2, 3] : [number, number, number]
|
||||
>1 : number
|
||||
>2 : number
|
||||
>3 : number
|
||||
|
||||
export { a, b };
|
||||
>a : number
|
||||
>b : number
|
||||
|
14
tests/cases/compiler/controlFlowOuterVariable.ts
Normal file
14
tests/cases/compiler/controlFlowOuterVariable.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
// @strictNullChecks: true
|
||||
|
||||
// Repros from #10641
|
||||
|
||||
const CONFIG = {
|
||||
foo: '',
|
||||
setFoo: function(foo: string) {
|
||||
CONFIG.foo = foo;
|
||||
}
|
||||
};
|
||||
|
||||
const helper = function<T>(t: T[]) {
|
||||
helper(t.slice(1));
|
||||
}
|
4
tests/cases/compiler/exportArrayBindingPattern.ts
Normal file
4
tests/cases/compiler/exportArrayBindingPattern.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
// @module: commonjs
|
||||
// issue: https://github.com/Microsoft/TypeScript/issues/10778
|
||||
const [a, , b] = [1, 2, 3];
|
||||
export { a, b };
|
|
@ -107,55 +107,55 @@
|
|||
////function /*l*/l(param1: string) { /*9*/param1 = "hello"; }
|
||||
|
||||
goTo.marker('a');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n\nThis is fourth Line");
|
||||
verify.quickInfoIs("var a: string", "This is firstLine\nThis is second Line\n\nThis is fourth Line");
|
||||
|
||||
goTo.marker('b');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n\nThis is fourth Line");
|
||||
verify.quickInfoIs("var b: string", "This is firstLine\nThis is second Line\n\nThis is fourth Line");
|
||||
|
||||
goTo.marker('c');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n\nThis is fourth Line");
|
||||
verify.quickInfoIs("var c: string", "This is firstLine\nThis is second Line\n\nThis is fourth Line");
|
||||
|
||||
goTo.marker('d');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
verify.quickInfoIs("function d(param: string): void", "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs(undefined, "");
|
||||
verify.quickInfoIs("(parameter) param: string", "");
|
||||
|
||||
goTo.marker('e');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line");
|
||||
verify.quickInfoIs("function e(param: string): void", "This is firstLine\nThis is second Line");
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs(undefined, "");
|
||||
verify.quickInfoIs("(parameter) param: string", "");
|
||||
|
||||
goTo.marker('f');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
verify.quickInfoIs("function f(param1: string): void", "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
goTo.marker('3');
|
||||
verify.quickInfoIs(undefined, "first line of param\n\nparam information third line");
|
||||
verify.quickInfoIs("(parameter) param1: string", "first line of param\n\nparam information third line");
|
||||
|
||||
goTo.marker('g');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
verify.quickInfoIs("function g(param1: string): void", "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
goTo.marker('4');
|
||||
verify.quickInfoIs(undefined, "param information first line");
|
||||
verify.quickInfoIs("(parameter) param1: string", "param information first line");
|
||||
|
||||
goTo.marker('h');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
verify.quickInfoIs("function h(param1: string): void", "This is firstLine\nThis is second Line\n@random tag This should be third line");
|
||||
goTo.marker('5');
|
||||
verify.quickInfoIs(undefined, "param information first line\n\nparam information third line");
|
||||
verify.quickInfoIs("(parameter) param1: string", "param information first line\n\nparam information third line");
|
||||
|
||||
goTo.marker('i');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line");
|
||||
verify.quickInfoIs("function i(param1: string): void", "This is firstLine\nThis is second Line");
|
||||
goTo.marker('6');
|
||||
verify.quickInfoIs(undefined, "param information first line\n\nparam information third line");
|
||||
verify.quickInfoIs("(parameter) param1: string", "param information first line\n\nparam information third line");
|
||||
|
||||
goTo.marker('j');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line");
|
||||
verify.quickInfoIs("function j(param1: string): void", "This is firstLine\nThis is second Line");
|
||||
goTo.marker('7');
|
||||
verify.quickInfoIs(undefined, "param information first line\n\nparam information third line");
|
||||
verify.quickInfoIs("(parameter) param1: string", "param information first line\n\nparam information third line");
|
||||
|
||||
goTo.marker('k');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@randomtag \n\n random information first line\n\n random information third line");
|
||||
verify.quickInfoIs("function k(param1: string): void", "This is firstLine\nThis is second Line\n@randomtag \n\n random information first line\n\n random information third line");
|
||||
goTo.marker('8');
|
||||
verify.quickInfoIs(undefined, "hello ");
|
||||
verify.quickInfoIs("(parameter) param1: string", "hello ");
|
||||
|
||||
goTo.marker('l');
|
||||
verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line");
|
||||
verify.quickInfoIs("function l(param1: string): void", "This is firstLine\nThis is second Line");
|
||||
goTo.marker('9');
|
||||
verify.quickInfoIs(undefined, "first Line text\nblank line that shouldnt be shown when starting this \nsecond time information about the param again");
|
||||
verify.quickInfoIs("(parameter) param1: string", "first Line text\nblank line that shouldnt be shown when starting this \nsecond time information about the param again");
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
////var max2: Comparer = (x/*1*/x, y/*2*/y) => { return x/*3*/x.compareTo(y/*4*/y) };
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs('(parameter) xx: any', null);
|
||||
verify.quickInfoIs('(parameter) xx: any');
|
||||
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs('(parameter) yy: any', null);
|
||||
verify.quickInfoIs('(parameter) yy: any');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.quickInfoIs('(parameter) xx: any', null);
|
||||
verify.quickInfoIs('(parameter) xx: any');
|
||||
|
||||
goTo.marker('4');
|
||||
verify.quickInfoIs('(parameter) yy: any', null);
|
||||
verify.quickInfoIs('(parameter) yy: any');
|
||||
|
|
|
@ -130,7 +130,7 @@ declare namespace FourSlashInterface {
|
|||
errorExistsBetweenMarkers(startMarker: string, endMarker: string): void;
|
||||
errorExistsAfterMarker(markerName?: string): void;
|
||||
errorExistsBeforeMarker(markerName?: string): void;
|
||||
quickInfoIs(expectedText?: string, expectedDocumentation?: string): void;
|
||||
quickInfoIs(expectedText: string, expectedDocumentation?: string): void;
|
||||
quickInfoExists(): void;
|
||||
typeDefinitionCountIs(expectedCount: number): void;
|
||||
isValidBraceCompletionAtPosition(openingBrace?: string): void;
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
////};
|
||||
|
||||
goTo.marker();
|
||||
verify.quickInfoIs('(local var) xx: T', null);
|
||||
verify.quickInfoIs('(local var) xx: T');
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
////var v/*3*/3: G<G<A, B>, C>; // Ok
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs('var v1: G<A, C>', null);
|
||||
verify.quickInfoIs('var v1: G<A, C>');
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs('var v2: G<{\n a: string;\n}, C>', null);
|
||||
verify.quickInfoIs('var v2: G<{\n a: string;\n}, C>');
|
||||
goTo.marker('3');
|
||||
verify.quickInfoIs('var v3: G<G<A, B>, C>', null);
|
||||
verify.quickInfoIs('var v3: G<G<A, B>, C>');
|
||||
|
|
|
@ -11,19 +11,19 @@
|
|||
////var f/*6*/6: Foo<number> = new Foo<number>(3);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs('var f1: Foo<number>', null);
|
||||
verify.quickInfoIs('var f1: Foo<number>');
|
||||
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs('var f2: Foo<number>', null);
|
||||
verify.quickInfoIs('var f2: Foo<number>');
|
||||
|
||||
goTo.marker('3');
|
||||
verify.quickInfoIs('var f3: any', null);
|
||||
verify.quickInfoIs('var f3: any');
|
||||
|
||||
goTo.marker('4');
|
||||
verify.quickInfoIs('var f4: Foo<number>', null);
|
||||
verify.quickInfoIs('var f4: Foo<number>');
|
||||
|
||||
goTo.marker('5');
|
||||
verify.quickInfoIs('var f5: any', null);
|
||||
verify.quickInfoIs('var f5: any');
|
||||
|
||||
goTo.marker('6');
|
||||
verify.quickInfoIs('var f6: Foo<number>', null);
|
||||
verify.quickInfoIs('var f6: Foo<number>');
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
////}
|
||||
|
||||
goTo.marker();
|
||||
verify.quickInfoIs('class Container<T>', null);
|
||||
verify.quickInfoIs('class Container<T>');
|
|
@ -3,7 +3,7 @@
|
|||
////interface Fo/*1*/o<T/*2*/T extends Date> {}
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs('interface Foo<TT extends Date>', null);
|
||||
verify.quickInfoIs('interface Foo<TT extends Date>');
|
||||
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs('(type parameter) TT in Foo<TT extends Date>', null);
|
||||
verify.quickInfoIs('(type parameter) TT in Foo<TT extends Date>');
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
////var a = { f: /**/a
|
||||
|
||||
goTo.marker();
|
||||
verify.quickInfoIs("var a: any", null);
|
||||
verify.quickInfoIs("var a: any");
|
||||
|
|
Loading…
Reference in a new issue