Merge branch 'master' into literalTypesAlways

This commit is contained in:
Anders Hejlsberg 2016-09-11 10:05:38 -07:00
commit aeb899aecf
47 changed files with 607 additions and 365 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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.

View file

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

View file

@ -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,

View file

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

View file

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

View file

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

View file

@ -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,

View file

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

View file

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

View file

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

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

View file

@ -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[] = [];

View file

@ -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,

View file

@ -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),

View file

@ -46,6 +46,7 @@
"classifier.ts",
"completions.ts",
"documentHighlights.ts",
"documentRegistry.ts",
"findAllReferences.ts",
"goToDefinition.ts",
"jsDoc.ts",

View file

@ -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 = "";

View file

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

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

View 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, --, --))
}

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

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

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

View 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

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

View file

@ -0,0 +1,4 @@
// @module: commonjs
// issue: https://github.com/Microsoft/TypeScript/issues/10778
const [a, , b] = [1, 2, 3];
export { a, b };

View file

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

View file

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

View file

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

View file

@ -6,4 +6,4 @@
////};
goTo.marker();
verify.quickInfoIs('(local var) xx: T', null);
verify.quickInfoIs('(local var) xx: T');

View file

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

View file

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

View file

@ -5,4 +5,4 @@
////}
goTo.marker();
verify.quickInfoIs('class Container<T>', null);
verify.quickInfoIs('class Container<T>');

View file

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

View file

@ -3,4 +3,4 @@
////var a = { f: /**/a
goTo.marker();
verify.quickInfoIs("var a: any", null);
verify.quickInfoIs("var a: any");