Skip to content

Commit 3721382

Browse files
author
Yui T
committed
Merge branch 'master' into reportDeclarationEmitErrors
2 parents c91c52d + 7aac8d5 commit 3721382

File tree

104 files changed

+768
-440
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+768
-440
lines changed

src/compiler/checker.ts

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ module ts {
6565
symbolToString: symbolToString,
6666
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType,
6767
getRootSymbol: getRootSymbol,
68-
getContextualType: getContextualType
68+
getContextualType: getContextualType,
69+
getFullyQualifiedName: getFullyQualifiedName
6970
};
7071

7172
var undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
@@ -2431,7 +2432,7 @@ module ts {
24312432
case SyntaxKind.Identifier:
24322433
case SyntaxKind.QualifiedName:
24332434
var symbol = getSymbolInfo(node);
2434-
return getDeclaredTypeOfSymbol(symbol);
2435+
return symbol && getDeclaredTypeOfSymbol(symbol);
24352436
default:
24362437
return unknownType;
24372438
}
@@ -3471,41 +3472,6 @@ module ts {
34713472
return getAncestor(node, kind) !== undefined;
34723473
}
34733474

3474-
function getAncestor(node: Node, kind: SyntaxKind): Node {
3475-
switch (kind) {
3476-
// special-cases that can be come first
3477-
case SyntaxKind.ClassDeclaration:
3478-
while (node) {
3479-
switch (node.kind) {
3480-
case SyntaxKind.ClassDeclaration:
3481-
return <ClassDeclaration>node;
3482-
case SyntaxKind.EnumDeclaration:
3483-
case SyntaxKind.InterfaceDeclaration:
3484-
case SyntaxKind.ModuleDeclaration:
3485-
case SyntaxKind.ImportDeclaration:
3486-
// early exit cases - declarations cannot be nested in classes
3487-
return undefined;
3488-
default:
3489-
node = node.parent;
3490-
continue;
3491-
}
3492-
}
3493-
break;
3494-
default:
3495-
while (node) {
3496-
if (node.kind === kind) {
3497-
return node;
3498-
}
3499-
else {
3500-
node = node.parent;
3501-
}
3502-
}
3503-
break;
3504-
}
3505-
3506-
return undefined;
3507-
}
3508-
35093475
// EXPRESSION TYPE CHECKING
35103476

35113477
function checkIdentifier(node: Identifier): Type {
@@ -3852,6 +3818,11 @@ module ts {
38523818
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
38533819
// be "pushed" onto a node using the contextualType property.
38543820
function getContextualType(node: Expression): Type {
3821+
if (isInsideWithStatementBody(node)) {
3822+
// We cannot answer semantic questions within a with block, do not proceed any further
3823+
return undefined;
3824+
}
3825+
38553826
if (node.contextualType) {
38563827
return node.contextualType;
38573828
}
@@ -6717,7 +6688,20 @@ module ts {
67176688
return findChildAtPosition(sourceFile);
67186689
}
67196690

6720-
function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] {
6691+
function isInsideWithStatementBody(node: Node): boolean {
6692+
if (node) {
6693+
while (node.parent) {
6694+
if (node.parent.kind === SyntaxKind.WithStatement && (<WithStatement>node.parent).statement === node) {
6695+
return true;
6696+
}
6697+
node = node.parent;
6698+
}
6699+
}
6700+
6701+
return false;
6702+
}
6703+
6704+
function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]{
67216705
var symbols: SymbolTable = {};
67226706
var memberFlags: NodeFlags = 0;
67236707
function copySymbol(symbol: Symbol, meaning: SymbolFlags) {
@@ -6737,6 +6721,12 @@ module ts {
67376721
}
67386722
}
67396723
}
6724+
6725+
if (isInsideWithStatementBody(location)) {
6726+
// We cannot answer semantic questions within a with block, do not proceed any further
6727+
return [];
6728+
}
6729+
67406730
while (location) {
67416731
if (location.locals && !isGlobalSourceFile(location)) {
67426732
copySymbols(location.locals, meaning);
@@ -7009,6 +6999,11 @@ module ts {
70096999
}
70107000

70117001
function getSymbolInfo(node: Node) {
7002+
if (isInsideWithStatementBody(node)) {
7003+
// We cannot answer semantic questions within a with block, do not proceed any further
7004+
return undefined;
7005+
}
7006+
70127007
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
70137008
// This is a declaration, call getSymbolOfNode
70147009
return getSymbolOfNode(node.parent);
@@ -7063,9 +7058,15 @@ module ts {
70637058
}
70647059

70657060
function getTypeOfNode(node: Node): Type {
7061+
if (isInsideWithStatementBody(node)) {
7062+
// We cannot answer semantic questions within a with block, do not proceed any further
7063+
return unknownType;
7064+
}
7065+
70667066
if (isExpression(node)) {
70677067
return getTypeOfExpression(<Expression>node);
70687068
}
7069+
70697070
if (isTypeNode(node)) {
70707071
return getTypeFromTypeNode(<TypeNode>node);
70717072
}
@@ -7078,7 +7079,7 @@ module ts {
70787079

70797080
if (isTypeDeclarationName(node)) {
70807081
var symbol = getSymbolInfo(node);
7081-
return getDeclaredTypeOfSymbol(symbol);
7082+
return symbol && getDeclaredTypeOfSymbol(symbol);
70827083
}
70837084

70847085
if (isDeclaration(node)) {
@@ -7089,12 +7090,12 @@ module ts {
70897090

70907091
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
70917092
var symbol = getSymbolInfo(node);
7092-
return getTypeOfSymbol(symbol);
7093+
return symbol && getTypeOfSymbol(symbol);
70937094
}
70947095

70957096
if (isInRightSideOfImportOrExportAssignment(node)) {
70967097
var symbol = getSymbolInfo(node);
7097-
var declaredType = getDeclaredTypeOfSymbol(symbol);
7098+
var declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
70987099
return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
70997100
}
71007101

@@ -7146,7 +7147,7 @@ module ts {
71467147
}
71477148

71487149
function getRootSymbol(symbol: Symbol) {
7149-
return (symbol.flags & SymbolFlags.Transient) ? getSymbolLinks(symbol).target : symbol;
7150+
return ((symbol.flags & SymbolFlags.Transient) && getSymbolLinks(symbol).target) || symbol;
71507151
}
71517152

71527153
// Emitter support

src/compiler/parser.ts

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,39 @@ module ts {
531531
return false;
532532
}
533533

534+
export function getAncestor(node: Node, kind: SyntaxKind): Node {
535+
switch (kind) {
536+
// special-cases that can be come first
537+
case SyntaxKind.ClassDeclaration:
538+
while (node) {
539+
switch (node.kind) {
540+
case SyntaxKind.ClassDeclaration:
541+
return <ClassDeclaration>node;
542+
case SyntaxKind.EnumDeclaration:
543+
case SyntaxKind.InterfaceDeclaration:
544+
case SyntaxKind.ModuleDeclaration:
545+
case SyntaxKind.ImportDeclaration:
546+
// early exit cases - declarations cannot be nested in classes
547+
return undefined;
548+
default:
549+
node = node.parent;
550+
continue;
551+
}
552+
}
553+
break;
554+
default:
555+
while (node) {
556+
if (node.kind === kind) {
557+
return node;
558+
}
559+
node = node.parent;
560+
}
561+
break;
562+
}
563+
564+
return undefined;
565+
}
566+
534567
enum ParsingContext {
535568
SourceElements, // Elements in source file
536569
ModuleElements, // Elements in module declaration
@@ -2200,10 +2233,38 @@ module ts {
22002233

22012234
function parseCallAndAccess(expr: Expression, inNewExpression: boolean): Expression {
22022235
while (true) {
2236+
var dotStart = scanner.getTokenPos();
22032237
if (parseOptional(SyntaxKind.DotToken)) {
22042238
var propertyAccess = <PropertyAccess>createNode(SyntaxKind.PropertyAccess, expr.pos);
2239+
// Technically a keyword is valid here as all keywords are identifier names.
2240+
// However, often we'll encounter this in error situations when the keyword
2241+
// is actually starting another valid construct.
2242+
//
2243+
// So, we check for the following specific case:
2244+
//
2245+
// name.
2246+
// keyword identifierNameOrKeyword
2247+
//
2248+
// Note: the newlines are important here. For example, if that above code
2249+
// were rewritten into:
2250+
//
2251+
// name.keyword
2252+
// identifierNameOrKeyword
2253+
//
2254+
// Then we would consider it valid. That's because ASI would take effect and
2255+
// the code would be implicitly: "name.keyword; identifierNameOrKeyword".
2256+
// In the first case though, ASI will not take effect because there is not a
2257+
// line terminator after the keyword.
2258+
if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord() && lookAhead(() => scanner.isReservedWord())) {
2259+
grammarErrorAtPos(dotStart, scanner.getStartPos() - dotStart, Diagnostics.Identifier_expected);
2260+
var id = <Identifier>createMissingNode();
2261+
}
2262+
else {
2263+
var id = parseIdentifierName();
2264+
}
2265+
22052266
propertyAccess.left = expr;
2206-
propertyAccess.right = parseIdentifierName();
2267+
propertyAccess.right = id;
22072268
expr = finishNode(propertyAccess);
22082269
continue;
22092270
}
@@ -3754,7 +3815,7 @@ module ts {
37543815
: undefined);
37553816
}
37563817

3757-
scanner = createScanner(languageVersion, sourceText, scanError, onComment);
3818+
scanner = createScanner(languageVersion, /*skipTrivia*/ true, sourceText, scanError, onComment);
37583819
var rootNodeFlags: NodeFlags = 0;
37593820
if (fileExtensionIs(filename, ".d.ts")) {
37603821
rootNodeFlags = NodeFlags.DeclarationFile;

src/compiler/scanner.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ module ts {
460460
ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
461461
}
462462

463-
export function createScanner(languageVersion: ScriptTarget, text?: string, onError?: ErrorCallback, onComment?: CommentCallback): Scanner {
463+
export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, text?: string, onError?: ErrorCallback, onComment?: CommentCallback): Scanner {
464464
var pos: number; // Current position (end position of text of current token)
465465
var len: number; // Length of text
466466
var startPos: number; // Start position of whitespace before current token
@@ -694,12 +694,34 @@ module ts {
694694
case CharacterCodes.lineFeed:
695695
case CharacterCodes.carriageReturn:
696696
precedingLineBreak = true;
697+
if (skipTrivia) {
698+
pos++;
699+
continue;
700+
}
701+
else {
702+
if (ch === CharacterCodes.carriageReturn && pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
703+
// consume both CR and LF
704+
pos += 2;
705+
}
706+
else {
707+
pos++;
708+
}
709+
return token = SyntaxKind.NewLineTrivia;
710+
}
697711
case CharacterCodes.tab:
698712
case CharacterCodes.verticalTab:
699713
case CharacterCodes.formFeed:
700714
case CharacterCodes.space:
701-
pos++;
702-
continue;
715+
if (skipTrivia) {
716+
pos++;
717+
continue;
718+
}
719+
else {
720+
while (pos < len && isWhiteSpace(text.charCodeAt(pos))) {
721+
pos++;
722+
}
723+
return token = SyntaxKind.WhitespaceTrivia;
724+
}
703725
case CharacterCodes.exclamation:
704726
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
705727
if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
@@ -776,7 +798,13 @@ module ts {
776798
if (onComment) {
777799
onComment(tokenPos, pos);
778800
}
779-
continue;
801+
802+
if (skipTrivia) {
803+
continue;
804+
}
805+
else {
806+
return token = SyntaxKind.SingleLineCommentTrivia;
807+
}
780808
}
781809
// Multi-line comment
782810
if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
@@ -806,7 +834,12 @@ module ts {
806834
onComment(tokenPos, pos);
807835
}
808836

809-
continue;
837+
if (skipTrivia) {
838+
continue;
839+
}
840+
else {
841+
return token = SyntaxKind.MultiLineCommentTrivia;
842+
}
810843
}
811844

812845
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {

src/compiler/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ module ts {
1212
export enum SyntaxKind {
1313
Unknown,
1414
EndOfFileToken,
15+
SingleLineCommentTrivia,
16+
MultiLineCommentTrivia,
17+
NewLineTrivia,
18+
WhitespaceTrivia,
1519
// Literals
1620
NumericLiteral,
1721
StringLiteral,
@@ -634,6 +638,7 @@ module ts {
634638
getApparentType(type: Type): ApparentType;
635639
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
636640
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
641+
getFullyQualifiedName(symbol: Symbol): string;
637642
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
638643
getRootSymbol(symbol: Symbol): Symbol;
639644
getContextualType(node: Node): Type;

src/harness/fourslash.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,44 @@ module FourSlash {
898898
}
899899
}
900900

901+
private validate(name: string, expected: string, actual: string) {
902+
if (expected && expected !== actual) {
903+
throw new Error("Expected " + name + " '" + expected + "'. Got '" + actual + "' instead.");
904+
}
905+
}
906+
907+
public verifyRenameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) {
908+
var renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
909+
if (!renameInfo.canRename) {
910+
throw new Error("Rename did not succeed");
911+
}
912+
913+
this.validate("displayName", displayName, renameInfo.displayName);
914+
this.validate("fullDisplayName", fullDisplayName, renameInfo.fullDisplayName);
915+
this.validate("kind", kind, renameInfo.kind);
916+
this.validate("kindModifiers", kindModifiers, renameInfo.kindModifiers);
917+
918+
if (this.getRanges().length !== 1) {
919+
throw new Error("Expected a single range to be selected in the test file.");
920+
}
921+
922+
var expectedRange = this.getRanges()[0];
923+
if (renameInfo.triggerSpan.start() !== expectedRange.start ||
924+
renameInfo.triggerSpan.end() !== expectedRange.end) {
925+
throw new Error("Expected triggerSpan [" + expectedRange.start + "," + expectedRange.end + "). Got [" +
926+
renameInfo.triggerSpan.start() + "," + renameInfo.triggerSpan.end() + ") instead.");
927+
}
928+
}
929+
930+
public verifyRenameInfoFailed(message?: string) {
931+
var renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
932+
if (renameInfo.canRename) {
933+
throw new Error("Rename was expected to fail");
934+
}
935+
936+
this.validate("error", message, renameInfo.localizedErrorMessage);
937+
}
938+
901939
//private getFormalParameter() {
902940
// var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
903941
// return help.formal;

0 commit comments

Comments
 (0)