Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add isStringLiteralLike helper #21953

Merged
1 commit merged into from
Feb 14, 2018
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
4 changes: 2 additions & 2 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -760,11 +760,11 @@ namespace ts {
}

function isNarrowingTypeofOperands(expr1: Expression, expr2: Expression) {
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && (expr2.kind === SyntaxKind.StringLiteral || expr2.kind === SyntaxKind.NoSubstitutionTemplateLiteral);
return isTypeOfExpression(expr1) && isNarrowableOperand(expr1.expression) && isStringLiteralLike(expr2);
}

function isNarrowableInOperands(left: Expression, right: Expression) {
return (left.kind === SyntaxKind.StringLiteral || left.kind === SyntaxKind.NoSubstitutionTemplateLiteral) && isNarrowingExpression(right);
return isStringLiteralLike(left) && isNarrowingExpression(right);
}

function isNarrowingBinaryExpression(expr: BinaryExpression) {
Expand Down
23 changes: 10 additions & 13 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2033,12 +2033,9 @@ namespace ts {
}

function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage, isForAugmentation = false): Symbol {
if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral && moduleReferenceExpression.kind !== SyntaxKind.NoSubstitutionTemplateLiteral) {
return;
}

const moduleReferenceLiteral = <LiteralExpression>moduleReferenceExpression;
return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral, isForAugmentation);
return isStringLiteralLike(moduleReferenceExpression)
? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, moduleReferenceExpression, isForAugmentation)
: undefined;
}

function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node, isForAugmentation = false): Symbol {
Expand Down Expand Up @@ -12946,11 +12943,11 @@ namespace ts {
const operator = expr.operatorToken.kind;
const left = getReferenceCandidate(expr.left);
const right = getReferenceCandidate(expr.right);
if (left.kind === SyntaxKind.TypeOfExpression && (right.kind === SyntaxKind.StringLiteral || right.kind === SyntaxKind.NoSubstitutionTemplateLiteral)) {
return narrowTypeByTypeof(type, <TypeOfExpression>left, operator, <LiteralExpression>right, assumeTrue);
if (left.kind === SyntaxKind.TypeOfExpression && isStringLiteralLike(right)) {
return narrowTypeByTypeof(type, <TypeOfExpression>left, operator, right, assumeTrue);
}
if (right.kind === SyntaxKind.TypeOfExpression && (left.kind === SyntaxKind.StringLiteral || left.kind === SyntaxKind.NoSubstitutionTemplateLiteral)) {
return narrowTypeByTypeof(type, <TypeOfExpression>right, operator, <LiteralExpression>left, assumeTrue);
if (right.kind === SyntaxKind.TypeOfExpression && isStringLiteralLike(left)) {
return narrowTypeByTypeof(type, <TypeOfExpression>right, operator, left, assumeTrue);
}
if (isMatchingReference(reference, left)) {
return narrowTypeByEquality(type, operator, right, assumeTrue);
Expand All @@ -12972,8 +12969,8 @@ namespace ts {
return narrowTypeByInstanceof(type, expr, assumeTrue);
case SyntaxKind.InKeyword:
const target = getReferenceCandidate(expr.right);
if ((expr.left.kind === SyntaxKind.StringLiteral || expr.left.kind === SyntaxKind.NoSubstitutionTemplateLiteral) && isMatchingReference(reference, target)) {
return narrowByInKeyword(type, <LiteralExpression>expr.left, assumeTrue);
if (isStringLiteralLike(expr.left) && isMatchingReference(reference, target)) {
return narrowByInKeyword(type, expr.left, assumeTrue);
}
break;
case SyntaxKind.CommaToken:
Expand Down Expand Up @@ -19599,7 +19596,7 @@ namespace ts {
return nullWideningType;
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.StringLiteral:
return getFreshTypeOfLiteralType(getLiteralType((node as LiteralExpression).text));
return getFreshTypeOfLiteralType(getLiteralType((node as StringLiteralLike).text));
case SyntaxKind.NumericLiteral:
checkGrammarNumericLiteral(node as NumericLiteral);
return getFreshTypeOfLiteralType(getLiteralType(+(node as NumericLiteral).text));
Expand Down
3 changes: 1 addition & 2 deletions src/compiler/transformers/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,8 @@ namespace ts {
* - this is mostly subjective beyond the requirement that the expression not be sideeffecting
*/
export function isSimpleCopiableExpression(expression: Expression) {
return expression.kind === SyntaxKind.StringLiteral ||
return isStringLiteralLike(expression) ||
expression.kind === SyntaxKind.NumericLiteral ||
expression.kind === SyntaxKind.NoSubstitutionTemplateLiteral ||
isKeyword(expression.kind) ||
isIdentifier(expression);
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,7 @@ namespace ts {
/* @internal */ singleQuote?: boolean;
}

/* @internal */ export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;

// Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
// Consider 'Expression'. Without the brand, 'Expression' is actually no different
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5947,4 +5947,8 @@ namespace ts {
export function isTypeReferenceType(node: Node): node is TypeReferenceType {
return node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ExpressionWithTypeArguments;
}

export function isStringLiteralLike(node: Node): node is StringLiteralLike {
return node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
}
2 changes: 1 addition & 1 deletion src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace ts.Completions {
const contextToken = findPrecedingToken(position, sourceFile);

if (isInString(sourceFile, position, contextToken)) {
return !contextToken || !isStringLiteral(contextToken) && !isNoSubstitutionTemplateLiteral(contextToken)
return !contextToken || !isStringLiteralLike(contextToken)
? undefined
: convertStringLiteralCompletions(getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host), sourceFile, typeChecker, log);
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/findAllReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ namespace ts.FindAllReferences.Core {
}

function isModuleReferenceLocation(node: ts.Node): boolean {
if (node.kind !== SyntaxKind.StringLiteral && node.kind !== SyntaxKind.NoSubstitutionTemplateLiteral) {
if (!isStringLiteralLike(node)) {
return false;
}
switch (node.parent.kind) {
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ declare namespace ts {
interface StringLiteral extends LiteralExpression {
kind: SyntaxKind.StringLiteral;
}
type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
interface Expression extends Node {
_expressionBrand: any;
}
Expand Down Expand Up @@ -3249,6 +3250,7 @@ declare namespace ts {
function isSetAccessor(node: Node): node is SetAccessorDeclaration;
function isGetAccessor(node: Node): node is GetAccessorDeclaration;
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement;
function isStringLiteralLike(node: Node): node is StringLiteralLike;
}
declare namespace ts {
type ErrorCallback = (message: DiagnosticMessage, length: number) => void;
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ declare namespace ts {
interface StringLiteral extends LiteralExpression {
kind: SyntaxKind.StringLiteral;
}
type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
interface Expression extends Node {
_expressionBrand: any;
}
Expand Down Expand Up @@ -3304,6 +3305,7 @@ declare namespace ts {
function isSetAccessor(node: Node): node is SetAccessorDeclaration;
function isGetAccessor(node: Node): node is GetAccessorDeclaration;
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement;
function isStringLiteralLike(node: Node): node is StringLiteralLike;
}
declare namespace ts {
function createNode(kind: SyntaxKind, pos?: number, end?: number): Node;
Expand Down