Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2061,7 +2061,7 @@ namespace ts {
return <TemplateMiddle | TemplateTail>fragment;
}

function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode {
function parseLiteralLikeNode(kind: SyntaxKind): LiteralExpression | LiteralLikeNode {
const node = <LiteralExpression>createNode(kind);
const text = scanner.getTokenValue();
node.text = text;
Expand Down Expand Up @@ -2611,11 +2611,31 @@ namespace ts {
return token() === SyntaxKind.DotToken ? undefined : node;
}

function parseLiteralTypeNode(): LiteralTypeNode {
const node = <LiteralTypeNode>createNode(SyntaxKind.LiteralType);
node.literal = parseSimpleUnaryExpression();
finishNode(node);
return node;
function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode {
const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode;
let unaryMinusExpression: PrefixUnaryExpression;
if (negative) {
unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression;
unaryMinusExpression.operator = SyntaxKind.MinusToken;
nextToken();
}
let expression: UnaryExpression;
switch (token()) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
expression = parseLiteralLikeNode(token()) as LiteralExpression;
break;
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
expression = parseTokenNode();
}
if (negative) {
unaryMinusExpression.operand = expression;
finishNode(unaryMinusExpression);
expression = unaryMinusExpression;
}
node.literal = expression;
return finishNode(node);
}

function nextTokenIsNumericLiteral() {
Expand Down Expand Up @@ -2650,7 +2670,7 @@ namespace ts {
case SyntaxKind.FalseKeyword:
return parseLiteralTypeNode();
case SyntaxKind.MinusToken:
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode() : parseTypeReference();
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
case SyntaxKind.VoidKeyword:
case SyntaxKind.NullKeyword:
return parseTokenNode<TypeNode>();
Expand Down
90 changes: 90 additions & 0 deletions tests/baselines/reference/expressionTypeNodeShouldError.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
tests/cases/compiler/base.d.ts(1,23): error TS1005: ',' expected.
tests/cases/compiler/base.d.ts(1,34): error TS1005: '=' expected.
tests/cases/compiler/boolean.ts(7,23): error TS1005: ',' expected.
tests/cases/compiler/boolean.ts(7,24): error TS1134: Variable declaration expected.
tests/cases/compiler/boolean.ts(11,16): error TS2304: Cannot find name 'document'.
tests/cases/compiler/boolean.ts(12,22): error TS1005: ';' expected.
tests/cases/compiler/number.ts(7,26): error TS1005: ',' expected.
tests/cases/compiler/number.ts(7,27): error TS1134: Variable declaration expected.
tests/cases/compiler/number.ts(11,16): error TS2304: Cannot find name 'document'.
tests/cases/compiler/number.ts(12,20): error TS1005: ';' expected.
tests/cases/compiler/string.ts(7,20): error TS1005: ',' expected.
tests/cases/compiler/string.ts(7,21): error TS1134: Variable declaration expected.
tests/cases/compiler/string.ts(11,15): error TS2304: Cannot find name 'document'.
tests/cases/compiler/string.ts(12,19): error TS1005: ';' expected.


==== tests/cases/compiler/base.d.ts (2 errors) ====
declare const x: "foo".charCodeAt(0);
~
!!! error TS1005: ',' expected.
~
!!! error TS1005: '=' expected.

==== tests/cases/compiler/string.ts (4 errors) ====
interface String {
typeof<T>(x: T): T;
}

class C {
foo() {
const x: "".typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}

const nodes = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType = "".typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.

==== tests/cases/compiler/number.ts (4 errors) ====
interface Number {
typeof<T>(x: T): T;
}

class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}

const nodes2 = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType2 = 4..typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.

==== tests/cases/compiler/boolean.ts (4 errors) ====
interface Boolean {
typeof<T>(x: T): T;
}

class C3 {
foo() {
const x: false.typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}

const nodes3 = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType3 = true.typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.


85 changes: 85 additions & 0 deletions tests/baselines/reference/expressionTypeNodeShouldError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//// [tests/cases/compiler/expressionTypeNodeShouldError.ts] ////

//// [base.d.ts]
declare const x: "foo".charCodeAt(0);

//// [string.ts]
interface String {
typeof<T>(x: T): T;
}

class C {
foo() {
const x: "".typeof(this.foo);
}
}

const nodes = document.getElementsByTagName("li");
type ItemType = "".typeof(nodes.item(0));

//// [number.ts]
interface Number {
typeof<T>(x: T): T;
}

class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
}
}

const nodes2 = document.getElementsByTagName("li");
type ItemType2 = 4..typeof(nodes.item(0));

//// [boolean.ts]
interface Boolean {
typeof<T>(x: T): T;
}

class C3 {
foo() {
const x: false.typeof(this.foo);
}
}

const nodes3 = document.getElementsByTagName("li");
type ItemType3 = true.typeof(nodes.item(0));



//// [string.js]
var C = (function () {
function C() {
}
C.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C;
}());
var nodes = document.getElementsByTagName("li");
typeof (nodes.item(0));
//// [number.js]
var C2 = (function () {
function C2() {
}
C2.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C2;
}());
var nodes2 = document.getElementsByTagName("li");
typeof (nodes.item(0));
//// [boolean.js]
var C3 = (function () {
function C3() {
}
C3.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C3;
}());
var nodes3 = document.getElementsByTagName("li");
typeof (nodes.item(0));
45 changes: 45 additions & 0 deletions tests/cases/compiler/expressionTypeNodeShouldError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// @Filename: base.d.ts
declare const x: "foo".charCodeAt(0);

// @filename: string.ts
interface String {
typeof<T>(x: T): T;
}

class C {
foo() {
const x: "".typeof(this.foo);
}
}

const nodes = document.getElementsByTagName("li");
type ItemType = "".typeof(nodes.item(0));

// @filename: number.ts
interface Number {
typeof<T>(x: T): T;
}

class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
}
}

const nodes2 = document.getElementsByTagName("li");
type ItemType2 = 4..typeof(nodes.item(0));

// @filename: boolean.ts
interface Boolean {
typeof<T>(x: T): T;
}

class C3 {
foo() {
const x: false.typeof(this.foo);
}
}

const nodes3 = document.getElementsByTagName("li");
type ItemType3 = true.typeof(nodes.item(0));