mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 20:37:00 -05:00
Merge branch 'master' into literalTypes
# Conflicts: # src/compiler/checker.ts
This commit is contained in:
@@ -26,7 +26,8 @@ namespace ts.formatting {
|
||||
RescanGreaterThanToken,
|
||||
RescanSlashToken,
|
||||
RescanTemplateToken,
|
||||
RescanJsxIdentifier
|
||||
RescanJsxIdentifier,
|
||||
RescanJsxText,
|
||||
}
|
||||
|
||||
export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
|
||||
@@ -140,6 +141,10 @@ namespace ts.formatting {
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldRescanJsxText(node: Node): boolean {
|
||||
return node && node.kind === SyntaxKind.JsxText;
|
||||
}
|
||||
|
||||
function shouldRescanSlashToken(container: Node): boolean {
|
||||
return container.kind === SyntaxKind.RegularExpressionLiteral;
|
||||
}
|
||||
@@ -176,6 +181,8 @@ namespace ts.formatting {
|
||||
? ScanAction.RescanTemplateToken
|
||||
: shouldRescanJsxIdentifier(n)
|
||||
? ScanAction.RescanJsxIdentifier
|
||||
: shouldRescanJsxText(n)
|
||||
? ScanAction.RescanJsxText
|
||||
: ScanAction.Scan;
|
||||
|
||||
if (lastTokenInfo && expectedScanAction === lastScanAction) {
|
||||
@@ -215,6 +222,10 @@ namespace ts.formatting {
|
||||
currentToken = scanner.scanJsxIdentifier();
|
||||
lastScanAction = ScanAction.RescanJsxIdentifier;
|
||||
}
|
||||
else if (expectedScanAction === ScanAction.RescanJsxText) {
|
||||
currentToken = scanner.reScanJsxToken();
|
||||
lastScanAction = ScanAction.RescanJsxText;
|
||||
}
|
||||
else {
|
||||
lastScanAction = ScanAction.Scan;
|
||||
}
|
||||
|
||||
@@ -514,16 +514,6 @@ namespace ts {
|
||||
return str === str.toLowerCase();
|
||||
}
|
||||
|
||||
function startsWith(string: string, search: string) {
|
||||
for (let i = 0, n = search.length; i < n; i++) {
|
||||
if (string.charCodeAt(i) !== search.charCodeAt(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Assumes 'value' is already lowercase.
|
||||
function indexOfIgnoringCase(string: string, value: string): number {
|
||||
for (let i = 0, n = string.length - value.length; i <= n; i++) {
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace ts {
|
||||
* change range cannot be determined. However, in that case, incremental parsing will
|
||||
* not happen and the entire document will be re - parsed.
|
||||
*/
|
||||
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange;
|
||||
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined;
|
||||
|
||||
/** Releases all resources held by this script snapshot */
|
||||
dispose?(): void;
|
||||
@@ -180,9 +180,10 @@ namespace ts {
|
||||
];
|
||||
let jsDocCompletionEntries: CompletionEntry[];
|
||||
|
||||
function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject {
|
||||
const node = new NodeObject(kind, pos, end);
|
||||
node.flags = flags;
|
||||
function createNode(kind: SyntaxKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject | IdentifierObject {
|
||||
const node = kind >= SyntaxKind.FirstNode ? new NodeObject(kind, pos, end) :
|
||||
kind === SyntaxKind.Identifier ? new IdentifierObject(kind, pos, end) :
|
||||
new TokenObject(kind, pos, end);
|
||||
node.parent = parent;
|
||||
return node;
|
||||
}
|
||||
@@ -197,11 +198,11 @@ namespace ts {
|
||||
private _children: Node[];
|
||||
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
this.kind = kind;
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public getSourceFile(): SourceFile {
|
||||
@@ -246,7 +247,7 @@ namespace ts {
|
||||
const token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan();
|
||||
const textPos = scanner.getTextPos();
|
||||
if (textPos <= end) {
|
||||
nodes.push(createNode(token, pos, textPos, 0, this));
|
||||
nodes.push(createNode(token, pos, textPos, this));
|
||||
}
|
||||
pos = textPos;
|
||||
}
|
||||
@@ -254,7 +255,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
private createSyntaxList(nodes: NodeArray<Node>): Node {
|
||||
const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, 0, this);
|
||||
const list = <NodeObject>createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, this);
|
||||
list._children = [];
|
||||
let pos = nodes.pos;
|
||||
|
||||
@@ -345,6 +346,95 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
class TokenOrIdentifierObject implements Token {
|
||||
public kind: SyntaxKind;
|
||||
public pos: number;
|
||||
public end: number;
|
||||
public flags: NodeFlags;
|
||||
public parent: Node;
|
||||
public jsDocComments: JSDocComment[];
|
||||
public __tokenTag: any;
|
||||
|
||||
constructor(pos: number, end: number) {
|
||||
// Set properties in same order as NodeObject
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
}
|
||||
|
||||
public getSourceFile(): SourceFile {
|
||||
return getSourceFileOfNode(this);
|
||||
}
|
||||
|
||||
public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
|
||||
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
|
||||
}
|
||||
|
||||
public getFullStart(): number {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
public getEnd(): number {
|
||||
return this.end;
|
||||
}
|
||||
|
||||
public getWidth(sourceFile?: SourceFile): number {
|
||||
return this.getEnd() - this.getStart(sourceFile);
|
||||
}
|
||||
|
||||
public getFullWidth(): number {
|
||||
return this.end - this.pos;
|
||||
}
|
||||
|
||||
public getLeadingTriviaWidth(sourceFile?: SourceFile): number {
|
||||
return this.getStart(sourceFile) - this.pos;
|
||||
}
|
||||
|
||||
public getFullText(sourceFile?: SourceFile): string {
|
||||
return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
|
||||
}
|
||||
|
||||
public getText(sourceFile?: SourceFile): string {
|
||||
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
|
||||
}
|
||||
|
||||
public getChildCount(sourceFile?: SourceFile): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public getChildAt(index: number, sourceFile?: SourceFile): Node {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getChildren(sourceFile?: SourceFile): Node[] {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
public getFirstToken(sourceFile?: SourceFile): Node {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getLastToken(sourceFile?: SourceFile): Node {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
class TokenObject extends TokenOrIdentifierObject {
|
||||
public kind: SyntaxKind;
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
super(pos, end);
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
|
||||
class IdentifierObject extends TokenOrIdentifierObject {
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
super(pos, end);
|
||||
}
|
||||
}
|
||||
IdentifierObject.prototype.kind = SyntaxKind.Identifier;
|
||||
|
||||
class SymbolObject implements Symbol {
|
||||
flags: SymbolFlags;
|
||||
name: string;
|
||||
@@ -3259,14 +3349,14 @@ namespace ts {
|
||||
|
||||
let isJsDocTagName = false;
|
||||
|
||||
let start = new Date().getTime();
|
||||
let start = timestamp();
|
||||
const currentToken = getTokenAtPosition(sourceFile, position);
|
||||
log("getCompletionData: Get current token: " + (new Date().getTime() - start));
|
||||
log("getCompletionData: Get current token: " + (timestamp() - start));
|
||||
|
||||
start = new Date().getTime();
|
||||
start = timestamp();
|
||||
// Completion not allowed inside comments, bail out if this is the case
|
||||
const insideComment = isInsideComment(sourceFile, currentToken, position);
|
||||
log("getCompletionData: Is inside comment: " + (new Date().getTime() - start));
|
||||
log("getCompletionData: Is inside comment: " + (timestamp() - start));
|
||||
|
||||
if (insideComment) {
|
||||
// The current position is next to the '@' sign, when no tag name being provided yet.
|
||||
@@ -3309,9 +3399,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
start = new Date().getTime();
|
||||
start = timestamp();
|
||||
const previousToken = findPrecedingToken(position, sourceFile);
|
||||
log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start));
|
||||
log("getCompletionData: Get previous token 1: " + (timestamp() - start));
|
||||
|
||||
// The decision to provide completion depends on the contextToken, which is determined through the previousToken.
|
||||
// Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
|
||||
@@ -3320,9 +3410,9 @@ namespace ts {
|
||||
// Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
|
||||
// Skip this partial identifier and adjust the contextToken to the token that precedes it.
|
||||
if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) {
|
||||
const start = new Date().getTime();
|
||||
const start = timestamp();
|
||||
contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile);
|
||||
log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start));
|
||||
log("getCompletionData: Get previous token 2: " + (timestamp() - start));
|
||||
}
|
||||
|
||||
// Find the node where completion is requested on.
|
||||
@@ -3369,7 +3459,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const semanticStart = new Date().getTime();
|
||||
const semanticStart = timestamp();
|
||||
let isMemberCompletion: boolean;
|
||||
let isNewIdentifierLocation: boolean;
|
||||
let symbols: Symbol[] = [];
|
||||
@@ -3407,7 +3497,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
|
||||
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
|
||||
|
||||
return { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName };
|
||||
|
||||
@@ -3551,12 +3641,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isCompletionListBlocker(contextToken: Node): boolean {
|
||||
const start = new Date().getTime();
|
||||
const start = timestamp();
|
||||
const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) ||
|
||||
isSolelyIdentifierDefinitionLocation(contextToken) ||
|
||||
isDotOfNumericLiteral(contextToken) ||
|
||||
isInJsxText(contextToken);
|
||||
log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: isCompletionListBlocker: " + (timestamp() - start));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4205,10 +4295,11 @@ namespace ts {
|
||||
kindModifiers: getSymbolModifiers(symbol),
|
||||
sortText: "0",
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Map<string> {
|
||||
const start = new Date().getTime();
|
||||
const start = timestamp();
|
||||
const uniqueNames: Map<string> = {};
|
||||
if (symbols) {
|
||||
for (const symbol of symbols) {
|
||||
@@ -4223,7 +4314,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
|
||||
log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (timestamp() - start));
|
||||
return uniqueNames;
|
||||
}
|
||||
|
||||
@@ -4233,22 +4324,58 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
|
||||
if (argumentInfo) {
|
||||
// Get string literal completions from specialized signatures of the target
|
||||
return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo);
|
||||
if (node.parent.kind === SyntaxKind.PropertyAssignment && node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
// Get quoted name of properties of the object literal expression
|
||||
// i.e. interface ConfigFiles {
|
||||
// 'jspm:dev': string
|
||||
// }
|
||||
// let files: ConfigFiles = {
|
||||
// '/*completion position*/'
|
||||
// }
|
||||
//
|
||||
// function foo(c: ConfigFiles) {}
|
||||
// foo({
|
||||
// '/*completion position*/'
|
||||
// });
|
||||
return getStringLiteralCompletionEntriesFromPropertyAssignment(<ObjectLiteralElement>node.parent);
|
||||
}
|
||||
else if (isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) {
|
||||
// Get all names of properties on the expression
|
||||
// i.e. interface A {
|
||||
// 'prop1': string
|
||||
// }
|
||||
// let a: A;
|
||||
// a['/*completion position*/']
|
||||
return getStringLiteralCompletionEntriesFromElementAccess(node.parent);
|
||||
}
|
||||
else {
|
||||
// Otherwise, get the completions from the contextual type if one exists
|
||||
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
|
||||
if (argumentInfo) {
|
||||
// Get string literal completions from specialized signatures of the target
|
||||
// i.e. declare function f(a: 'A');
|
||||
// f("/*completion position*/")
|
||||
return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, node);
|
||||
}
|
||||
|
||||
// Get completion for string literal from string literal type
|
||||
// i.e. var x: "hi" | "hello" = "/*completion position*/"
|
||||
return getStringLiteralCompletionEntriesFromContextualType(<StringLiteral>node);
|
||||
}
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo) {
|
||||
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement) {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const type = typeChecker.getContextualType((<ObjectLiteralExpression>element.parent));
|
||||
const entries: CompletionEntry[] = [];
|
||||
if (type) {
|
||||
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, /*performCharacterChecks*/false);
|
||||
if (entries.length) {
|
||||
return { isMemberCompletion: true, isNewIdentifierLocation: true, entries };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo, location: Node) {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const candidates: Signature[] = [];
|
||||
const entries: CompletionEntry[] = [];
|
||||
@@ -7643,14 +7770,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) {
|
||||
let start = new Date().getTime();
|
||||
let start = timestamp();
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
|
||||
log("getIndentationAtPosition: getCurrentSourceFile: " + (timestamp() - start));
|
||||
|
||||
start = new Date().getTime();
|
||||
start = timestamp();
|
||||
|
||||
const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
|
||||
log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start));
|
||||
log("getIndentationAtPosition: computeIndentation : " + (timestamp() - start));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -8691,6 +8818,8 @@ namespace ts {
|
||||
function initializeServices() {
|
||||
objectAllocator = {
|
||||
getNodeConstructor: () => NodeObject,
|
||||
getTokenConstructor: () => TokenObject,
|
||||
getIdentifierConstructor: () => IdentifierObject,
|
||||
getSourceFileConstructor: () => SourceFileObject,
|
||||
getSymbolConstructor: () => SymbolObject,
|
||||
getTypeConstructor: () => TypeObject,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/// <reference path='services.ts' />
|
||||
|
||||
/* @internal */
|
||||
let debugObjectHost = (<any>this);
|
||||
let debugObjectHost = new Function("return this")();
|
||||
|
||||
// We need to use 'null' to interface with the managed side.
|
||||
/* tslint:disable:no-null-keyword */
|
||||
@@ -61,7 +61,7 @@ namespace ts {
|
||||
getLocalizedDiagnosticMessages(): string;
|
||||
getCancellationToken(): HostCancellationToken;
|
||||
getCurrentDirectory(): string;
|
||||
getDirectories(path: string): string[];
|
||||
getDirectories(path: string): string;
|
||||
getDefaultLibFileName(options: string): string;
|
||||
getNewLine?(): string;
|
||||
getProjectVersion?(): string;
|
||||
@@ -404,7 +404,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
public getDirectories(path: string): string[] {
|
||||
return this.shimHost.getDirectories(path);
|
||||
return JSON.parse(this.shimHost.getDirectories(path));
|
||||
}
|
||||
|
||||
public getDefaultLibFileName(options: CompilerOptions): string {
|
||||
@@ -423,7 +423,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
public isCancellationRequested(): boolean {
|
||||
const time = Date.now();
|
||||
const time = timestamp();
|
||||
const duration = Math.abs(time - this.lastCancellationCheckTime);
|
||||
if (duration > 10) {
|
||||
// Check no more than once every 10 ms.
|
||||
@@ -498,13 +498,13 @@ namespace ts {
|
||||
let start: number;
|
||||
if (logPerformance) {
|
||||
logger.log(actionDescription);
|
||||
start = Date.now();
|
||||
start = timestamp();
|
||||
}
|
||||
|
||||
const result = action();
|
||||
|
||||
if (logPerformance) {
|
||||
const end = Date.now();
|
||||
const end = timestamp();
|
||||
logger.log(`${actionDescription} completed in ${end - start} msec`);
|
||||
if (typeof result === "string") {
|
||||
let str = result;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": true,
|
||||
"pretty": true,
|
||||
"outFile": "../../built/local/typescriptServices.js",
|
||||
"sourceMap": true,
|
||||
"stripInternal": true,
|
||||
@@ -11,6 +13,7 @@
|
||||
},
|
||||
"files": [
|
||||
"../compiler/core.ts",
|
||||
"../compiler/performance.ts",
|
||||
"../compiler/sys.ts",
|
||||
"../compiler/types.ts",
|
||||
"../compiler/scanner.ts",
|
||||
|
||||
Reference in New Issue
Block a user