mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 21:06:50 -05:00
Merge branch 'master' into noImportClauseBuilders
Conflicts: src/services/services.ts
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
namespace ts.NavigateTo {
|
||||
type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration };
|
||||
|
||||
export function getNavigateToItems(program: Program, cancellationToken: CancellationTokenObject, searchValue: string, maxResultCount: number): NavigateToItem[] {
|
||||
export function getNavigateToItems(program: Program, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number): NavigateToItem[] {
|
||||
let patternMatcher = createPatternMatcher(searchValue);
|
||||
let rawItems: RawNavigateToItem[] = [];
|
||||
|
||||
|
||||
@@ -944,6 +944,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export interface HostCancellationToken {
|
||||
isCancellationRequested(): boolean;
|
||||
}
|
||||
|
||||
//
|
||||
// Public interface of the host of a language service instance.
|
||||
//
|
||||
@@ -955,7 +959,7 @@ namespace ts {
|
||||
getScriptVersion(fileName: string): string;
|
||||
getScriptSnapshot(fileName: string): IScriptSnapshot;
|
||||
getLocalizedDiagnosticMessages?(): any;
|
||||
getCancellationToken?(): CancellationToken;
|
||||
getCancellationToken?(): HostCancellationToken;
|
||||
getCurrentDirectory(): string;
|
||||
getDefaultLibFileName(options: CompilerOptions): string;
|
||||
log? (s: string): void;
|
||||
@@ -1615,26 +1619,6 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export class OperationCanceledException { }
|
||||
|
||||
export class CancellationTokenObject {
|
||||
|
||||
public static None: CancellationTokenObject = new CancellationTokenObject(null)
|
||||
|
||||
constructor(private cancellationToken: CancellationToken) {
|
||||
}
|
||||
|
||||
public isCancellationRequested() {
|
||||
return this.cancellationToken && this.cancellationToken.isCancellationRequested();
|
||||
}
|
||||
|
||||
public throwIfCancellationRequested(): void {
|
||||
if (this.isCancellationRequested()) {
|
||||
throw new OperationCanceledException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache host information about scrip Should be refreshed
|
||||
// at each language service public entry point, since we don't know when
|
||||
// set of scripts handled by the host changes.
|
||||
@@ -2401,6 +2385,21 @@ namespace ts {
|
||||
return ScriptElementKind.unknown;
|
||||
}
|
||||
|
||||
class CancellationTokenObject implements CancellationToken {
|
||||
constructor(private cancellationToken: HostCancellationToken) {
|
||||
}
|
||||
|
||||
public isCancellationRequested() {
|
||||
return this.cancellationToken && this.cancellationToken.isCancellationRequested();
|
||||
}
|
||||
|
||||
public throwIfCancellationRequested(): void {
|
||||
if (this.isCancellationRequested()) {
|
||||
throw new OperationCanceledException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry()): LanguageService {
|
||||
let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host);
|
||||
let ruleProvider: formatting.RulesProvider;
|
||||
@@ -2605,7 +2604,7 @@ namespace ts {
|
||||
function getSyntacticDiagnostics(fileName: string) {
|
||||
synchronizeHostData();
|
||||
|
||||
return program.getSyntacticDiagnostics(getValidSourceFile(fileName));
|
||||
return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2627,13 +2626,13 @@ namespace ts {
|
||||
// Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
|
||||
// Therefore only get diagnostics for given file.
|
||||
|
||||
let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile);
|
||||
let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken);
|
||||
if (!program.getCompilerOptions().declaration) {
|
||||
return semanticDiagnostics;
|
||||
}
|
||||
|
||||
// If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface
|
||||
let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile);
|
||||
let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken);
|
||||
return concatenate(semanticDiagnostics, declarationDiagnostics);
|
||||
}
|
||||
|
||||
@@ -2796,7 +2795,8 @@ namespace ts {
|
||||
|
||||
function getCompilerOptionsDiagnostics() {
|
||||
synchronizeHostData();
|
||||
return program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics());
|
||||
return program.getOptionsDiagnostics(cancellationToken).concat(
|
||||
program.getGlobalDiagnostics(cancellationToken));
|
||||
}
|
||||
|
||||
/// Completion
|
||||
@@ -3205,21 +3205,30 @@ namespace ts {
|
||||
}
|
||||
|
||||
function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | BindingPattern): boolean {
|
||||
// Object literal expression, look up possible property names from contextual type
|
||||
// We're looking up possible property names from contextual/inferred/declared type.
|
||||
isMemberCompletion = true;
|
||||
isNewIdentifierLocation = true;
|
||||
|
||||
let typeForObject: Type;
|
||||
let existingMembers: Declaration[];
|
||||
|
||||
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
// We are completing on contextual types, but may also include properties
|
||||
// other than those within the declared type.
|
||||
isNewIdentifierLocation = true;
|
||||
|
||||
typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
|
||||
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
|
||||
}
|
||||
else {
|
||||
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
// We are *only* completing on properties from the type being destructured.
|
||||
isNewIdentifierLocation = false;
|
||||
|
||||
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||
existingMembers = (<BindingPattern>objectLikeContainer).elements;
|
||||
}
|
||||
else {
|
||||
Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind);
|
||||
}
|
||||
|
||||
if (!typeForObject) {
|
||||
return false;
|
||||
@@ -5834,7 +5843,7 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
let emitOutput = program.emit(sourceFile, writeFile);
|
||||
let emitOutput = program.emit(sourceFile, writeFile, cancellationToken);
|
||||
|
||||
return {
|
||||
outputFiles,
|
||||
@@ -6082,6 +6091,26 @@ namespace ts {
|
||||
return convertClassifications(getEncodedSemanticClassifications(fileName, span));
|
||||
}
|
||||
|
||||
function checkForClassificationCancellation(kind: SyntaxKind) {
|
||||
// We don't want to actually call back into our host on every node to find out if we've
|
||||
// been canceled. That would be an enormous amount of chattyness, along with the all
|
||||
// the overhead of marshalling the data to/from the host. So instead we pick a few
|
||||
// reasonable node kinds to bother checking on. These node kinds represent high level
|
||||
// constructs that we would expect to see commonly, but just at a far less frequent
|
||||
// interval.
|
||||
//
|
||||
// For example, in checker.ts (around 750k) we only have around 600 of these constructs.
|
||||
// That means we're calling back into the host around every 1.2k of the file we process.
|
||||
// Lib.d.ts has similar numbers.
|
||||
switch (kind) {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
|
||||
function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications {
|
||||
synchronizeHostData();
|
||||
|
||||
@@ -6149,7 +6178,10 @@ namespace ts {
|
||||
function processNode(node: Node) {
|
||||
// Only walk into nodes that intersect the requested span.
|
||||
if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) {
|
||||
if (node.kind === SyntaxKind.Identifier && !nodeIsMissing(node)) {
|
||||
let kind = node.kind;
|
||||
checkForClassificationCancellation(kind);
|
||||
|
||||
if (kind === SyntaxKind.Identifier && !nodeIsMissing(node)) {
|
||||
let identifier = <Identifier>node;
|
||||
|
||||
// Only bother calling into the typechecker if this is an identifier that
|
||||
@@ -6516,6 +6548,8 @@ namespace ts {
|
||||
|
||||
// Ignore nodes that don't intersect the original span to classify.
|
||||
if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) {
|
||||
checkForClassificationCancellation(element.kind);
|
||||
|
||||
let children = element.getChildren(sourceFile);
|
||||
for (let i = 0, n = children.length; i < n; i++) {
|
||||
let child = children[i];
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace ts {
|
||||
getScriptVersion(fileName: string): string;
|
||||
getScriptSnapshot(fileName: string): ScriptSnapshotShim;
|
||||
getLocalizedDiagnosticMessages(): string;
|
||||
getCancellationToken(): CancellationToken;
|
||||
getCancellationToken(): HostCancellationToken;
|
||||
getCurrentDirectory(): string;
|
||||
getDefaultLibFileName(options: string): string;
|
||||
getNewLine?(): string;
|
||||
@@ -326,8 +326,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
public getCancellationToken(): CancellationToken {
|
||||
return this.shimHost.getCancellationToken();
|
||||
public getCancellationToken(): HostCancellationToken {
|
||||
var hostCancellationToken = this.shimHost.getCancellationToken();
|
||||
return new ThrottledCancellationToken(hostCancellationToken);
|
||||
}
|
||||
|
||||
public getCurrentDirectory(): string {
|
||||
@@ -346,6 +347,29 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/** A cancellation that throttles calls to the host */
|
||||
class ThrottledCancellationToken implements HostCancellationToken {
|
||||
// Store when we last tried to cancel. Checking cancellation can be expensive (as we have
|
||||
// to marshall over to the host layer). So we only bother actually checking once enough
|
||||
// time has passed.
|
||||
private lastCancellationCheckTime = 0;
|
||||
|
||||
constructor(private hostCancellationToken: HostCancellationToken) {
|
||||
}
|
||||
|
||||
public isCancellationRequested(): boolean {
|
||||
var time = Date.now();
|
||||
var duration = Math.abs(time - this.lastCancellationCheckTime);
|
||||
if (duration > 10) {
|
||||
// Check no more than once every 10 ms.
|
||||
this.lastCancellationCheckTime = time;
|
||||
return this.hostCancellationToken.isCancellationRequested();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class CoreServicesShimHostAdapter implements ParseConfigHost {
|
||||
|
||||
constructor(private shimHost: CoreServicesShimHost) {
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace ts.SignatureHelp {
|
||||
argumentCount: number;
|
||||
}
|
||||
|
||||
export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationTokenObject): SignatureHelpItems {
|
||||
export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems {
|
||||
let typeChecker = program.getTypeChecker();
|
||||
|
||||
// Decide whether to show signature help
|
||||
|
||||
Reference in New Issue
Block a user