mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into letConstES5Minus
This commit is contained in:
@@ -482,6 +482,16 @@ module ts {
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.Block:
|
||||
// do not treat function block a block-scope container
|
||||
// all block-scope locals that reside in this block should go to the function locals.
|
||||
// Otherwise this won't be considered as redeclaration of a block scoped local:
|
||||
// function foo() {
|
||||
// let x;
|
||||
// var x;
|
||||
// }
|
||||
// 'var x' will be placed into the function locals and 'let x' - into the locals of the block
|
||||
bindChildren(node, 0, /*isBlockScopeContainer*/ !isAnyFunction(node.parent));
|
||||
break;
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
|
||||
+42
-11
@@ -8198,32 +8198,61 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkCollisionWithConstDeclarations(node: VariableLikeDeclaration) {
|
||||
function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) {
|
||||
// - ScriptBody : StatementList
|
||||
// It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
|
||||
// also occurs in the VarDeclaredNames of StatementList.
|
||||
|
||||
// - Block : { StatementList }
|
||||
// It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
|
||||
// also occurs in the VarDeclaredNames of StatementList.
|
||||
|
||||
// Variable declarations are hoisted to the top of their function scope. They can shadow
|
||||
// block scoped declarations, which bind tighter. this will not be flagged as duplicate definition
|
||||
// by the binder as the declaration scope is different.
|
||||
// A non-initialized declaration is a no-op as the block declaration will resolve before the var
|
||||
// declaration. the problem is if the declaration has an initializer. this will act as a write to the
|
||||
// block declared value. this is fine for let, but not const.
|
||||
//
|
||||
// Only consider declarations with initializers, uninitialized var declarations will not
|
||||
// step on a const variable.
|
||||
// step on a let/const variable.
|
||||
// Do not consider let and const declarations, as duplicate block-scoped declarations
|
||||
// are handled by the binder.
|
||||
// We are only looking for var declarations that step on const declarations from a
|
||||
// We are only looking for var declarations that step on let\const declarations from a
|
||||
// different scope. e.g.:
|
||||
// var x = 0;
|
||||
// {
|
||||
// const x = 0;
|
||||
// var x = 0;
|
||||
// const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration
|
||||
// var x = 0; // symbol for this declaration will be 'symbol'
|
||||
// }
|
||||
if (node.initializer && (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) === 0) {
|
||||
var symbol = getSymbolOfNode(node);
|
||||
if (symbol.flags & SymbolFlags.FunctionScopedVariable) {
|
||||
var localDeclarationSymbol = resolveName(node, (<Identifier>node.name).text, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (localDeclarationSymbol && localDeclarationSymbol !== symbol && localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) {
|
||||
if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.Const) {
|
||||
error(node, Diagnostics.Cannot_redeclare_block_scoped_variable_0, symbolToString(localDeclarationSymbol));
|
||||
if (localDeclarationSymbol &&
|
||||
localDeclarationSymbol !== symbol &&
|
||||
localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) {
|
||||
if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) {
|
||||
|
||||
var varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList);
|
||||
var container =
|
||||
varDeclList.parent.kind === SyntaxKind.VariableStatement &&
|
||||
varDeclList.parent.parent;
|
||||
|
||||
// names of block-scoped and function scoped variables can collide only
|
||||
// if block scoped variable is defined in the function\module\source file scope (because of variable hoisting)
|
||||
var namesShareScope =
|
||||
container &&
|
||||
(container.kind === SyntaxKind.Block && isAnyFunction(container.parent) ||
|
||||
(container.kind === SyntaxKind.ModuleBlock && container.kind === SyntaxKind.ModuleDeclaration) ||
|
||||
container.kind === SyntaxKind.SourceFile);
|
||||
|
||||
// here we know that function scoped variable is shadowed by block scoped one
|
||||
// if they are defined in the same scope - binder has already reported redeclaration error
|
||||
// otherwise if variable has an initializer - show error that initialization will fail
|
||||
// since LHS will be block scoped name instead of function scoped
|
||||
if (!namesShareScope) {
|
||||
var name = symbolToString(localDeclarationSymbol);
|
||||
error(getErrorSpanForNode(node), Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8320,7 +8349,9 @@ module ts {
|
||||
if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature) {
|
||||
// We know we don't have a binding pattern or computed name here
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
checkCollisionWithConstDeclarations(node);
|
||||
if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
|
||||
checkVarDeclaredNamesNotShadowed(<VariableDeclaration | BindingElement>node);
|
||||
}
|
||||
checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
|
||||
checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
|
||||
|
||||
@@ -381,6 +381,7 @@ module ts {
|
||||
const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: { code: 4087, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to disallowed value 'NaN'." },
|
||||
Property_0_does_not_exist_on_const_enum_1: { code: 4088, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on 'const' enum '{1}'." },
|
||||
let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: { code: 4089, category: DiagnosticCategory.Error, key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations." },
|
||||
Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1: { code: 4090, category: DiagnosticCategory.Error, key: "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'." },
|
||||
The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
|
||||
Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
|
||||
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
|
||||
|
||||
@@ -1517,6 +1517,10 @@
|
||||
"category": "Error",
|
||||
"code": 4089
|
||||
},
|
||||
"Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4090
|
||||
},
|
||||
"The current host does not support the '{0}' option.": {
|
||||
"category": "Error",
|
||||
"code": 5001
|
||||
|
||||
+2
-2
@@ -332,7 +332,7 @@ module ts {
|
||||
var program = createProgram(fileNames, compilerOptions, compilerHost);
|
||||
var exitStatus = compileProgram();
|
||||
|
||||
var end = start - new Date().getTime();
|
||||
var end = new Date().getTime() - start;
|
||||
|
||||
if (compilerOptions.listFiles) {
|
||||
forEach(program.getSourceFiles(), file => {
|
||||
@@ -357,7 +357,7 @@ module ts {
|
||||
reportTimeStatistic("Bind time", ts.bindTime);
|
||||
reportTimeStatistic("Check time", ts.checkTime);
|
||||
reportTimeStatistic("Emit time", ts.emitTime);
|
||||
reportTimeStatistic("Total time", start - end);
|
||||
reportTimeStatistic("Total time", end);
|
||||
}
|
||||
|
||||
return { program, exitStatus };
|
||||
|
||||
@@ -795,9 +795,12 @@ module Harness {
|
||||
}
|
||||
}
|
||||
|
||||
export function createSourceFileAndAssertInvariants(fileName: string, sourceText: string, languageVersion: ts.ScriptTarget) {
|
||||
var result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ true);
|
||||
Utils.assertInvariants(result, /*parent:*/ undefined);
|
||||
export function createSourceFileAndAssertInvariants(fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, assertInvariants = true) {
|
||||
// Only set the parent nodes if we're asserting invariants. We don't need them otherwise.
|
||||
var result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ assertInvariants);
|
||||
if (assertInvariants) {
|
||||
Utils.assertInvariants(result, /*parent:*/ undefined);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -805,7 +808,6 @@ module Harness {
|
||||
export var defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest);
|
||||
export var defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + 'lib.core.es6.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest);
|
||||
|
||||
|
||||
// Cache these between executions so we don't have to re-parse them for every test
|
||||
export var fourslashFileName = 'fourslash.ts';
|
||||
export var fourslashSourceFile: ts.SourceFile;
|
||||
@@ -926,7 +928,8 @@ module Harness {
|
||||
settingsCallback?: (settings: ts.CompilerOptions) => void,
|
||||
options?: ts.CompilerOptions,
|
||||
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
|
||||
currentDirectory?: string) {
|
||||
currentDirectory?: string,
|
||||
assertInvariants = true) {
|
||||
|
||||
options = options || { noResolve: false };
|
||||
options.target = options.target || ts.ScriptTarget.ES3;
|
||||
@@ -1074,7 +1077,7 @@ module Harness {
|
||||
var register = (file: { unitName: string; content: string; }) => {
|
||||
if (file.content !== undefined) {
|
||||
var fileName = ts.normalizeSlashes(file.unitName);
|
||||
filemap[getCanonicalFileName(fileName)] = createSourceFileAndAssertInvariants(fileName, file.content, options.target);
|
||||
filemap[getCanonicalFileName(fileName)] = createSourceFileAndAssertInvariants(fileName, file.content, options.target, assertInvariants);
|
||||
}
|
||||
};
|
||||
inputFiles.forEach(register);
|
||||
|
||||
@@ -90,7 +90,8 @@ module RWC {
|
||||
/*settingsCallback*/ undefined, opts.options,
|
||||
// Since all Rwc json file specified current directory in its json file, we need to pass this information to compilerHost
|
||||
// so that when the host is asked for current directory, it should give the value from json rather than from process
|
||||
currentDirectory);
|
||||
currentDirectory,
|
||||
/*assertInvariants:*/ false);
|
||||
});
|
||||
|
||||
function getHarnessCompilerInputUnit(fileName: string) {
|
||||
|
||||
+123
-10
@@ -1143,6 +1143,9 @@ module ts {
|
||||
InMultiLineCommentTrivia,
|
||||
InSingleQuoteStringLiteral,
|
||||
InDoubleQuoteStringLiteral,
|
||||
InTemplateHeadOrNoSubstitutionTemplate,
|
||||
InTemplateMiddleOrTail,
|
||||
InTemplateSubstitutionPosition,
|
||||
}
|
||||
|
||||
export enum TokenClass {
|
||||
@@ -1168,7 +1171,26 @@ module ts {
|
||||
}
|
||||
|
||||
export interface Classifier {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
/**
|
||||
* Gives lexical classifications of tokens on a line without any syntactic context.
|
||||
* For instance, a token consisting of the text 'string' can be either an identifier
|
||||
* named 'string' or the keyword 'string', however, because this classifier is not aware,
|
||||
* it relies on certain heuristics to give acceptable results. For classifications where
|
||||
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
|
||||
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
|
||||
* lexical, syntactic, and semantic classifiers may issue the best user experience.
|
||||
*
|
||||
* @param text The text of a line to classify.
|
||||
* @param lexState The state of the lexical classifier at the end of the previous line.
|
||||
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
|
||||
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
|
||||
* certain heuristics may be used in its place; however, if there is a
|
||||
* syntactic classifier (syntacticClassifierAbsent=false), certain
|
||||
* classifications which may be incorrectly categorized will be given
|
||||
* back as Identifiers in order to allow the syntactic classifier to
|
||||
* subsume the classification.
|
||||
*/
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5617,6 +5639,28 @@ module ts {
|
||||
noRegexTable[SyntaxKind.TrueKeyword] = true;
|
||||
noRegexTable[SyntaxKind.FalseKeyword] = true;
|
||||
|
||||
// Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact)
|
||||
// classification on template strings. Because of the context free nature of templates,
|
||||
// the only precise way to classify a template portion would be by propagating the stack across
|
||||
// lines, just as we do with the end-of-line state. However, this is a burden for implementers,
|
||||
// and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead
|
||||
// flatten any nesting when the template stack is non-empty and encode it in the end-of-line state.
|
||||
// Situations in which this fails are
|
||||
// 1) When template strings are nested across different lines:
|
||||
// `hello ${ `world
|
||||
// ` }`
|
||||
//
|
||||
// Where on the second line, you will get the closing of a template,
|
||||
// a closing curly, and a new template.
|
||||
//
|
||||
// 2) When substitution expressions have curly braces and the curly brace falls on the next line:
|
||||
// `hello ${ () => {
|
||||
// return "world" } } `
|
||||
//
|
||||
// Where on the second line, you will get the 'return' keyword,
|
||||
// a string literal, and a template end consisting of '} } `'.
|
||||
var templateStack: SyntaxKind[] = [];
|
||||
|
||||
function isAccessibilityModifier(kind: SyntaxKind) {
|
||||
switch (kind) {
|
||||
case SyntaxKind.PublicKeyword:
|
||||
@@ -5650,13 +5694,19 @@ module ts {
|
||||
// if there are more cases we want the classifier to be better at.
|
||||
return true;
|
||||
}
|
||||
|
||||
// 'classifyKeywordsInGenerics' should be 'true' when a syntactic classifier is not present.
|
||||
function getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult {
|
||||
|
||||
// If there is a syntactic classifier ('syntacticClassifierAbsent' is false),
|
||||
// we will be more conservative in order to avoid conflicting with the syntactic classifier.
|
||||
function getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): ClassificationResult {
|
||||
var offset = 0;
|
||||
var token = SyntaxKind.Unknown;
|
||||
var lastNonTriviaToken = SyntaxKind.Unknown;
|
||||
|
||||
// Empty out the template stack for reuse.
|
||||
while (templateStack.length > 0) {
|
||||
templateStack.pop();
|
||||
}
|
||||
|
||||
// If we're in a string literal, then prepend: "\
|
||||
// (and a newline). That way when we lex we'll think we're still in a string literal.
|
||||
//
|
||||
@@ -5675,6 +5725,17 @@ module ts {
|
||||
text = "/*\n" + text;
|
||||
offset = 3;
|
||||
break;
|
||||
case EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate:
|
||||
text = "`\n" + text;
|
||||
offset = 2;
|
||||
break;
|
||||
case EndOfLineState.InTemplateMiddleOrTail:
|
||||
text = "}\n" + text;
|
||||
offset = 2;
|
||||
// fallthrough
|
||||
case EndOfLineState.InTemplateSubstitutionPosition:
|
||||
templateStack.push(SyntaxKind.TemplateHead);
|
||||
break;
|
||||
}
|
||||
|
||||
scanner.setText(text);
|
||||
@@ -5739,12 +5800,45 @@ module ts {
|
||||
token === SyntaxKind.StringKeyword ||
|
||||
token === SyntaxKind.NumberKeyword ||
|
||||
token === SyntaxKind.BooleanKeyword) {
|
||||
if (angleBracketStack > 0 && !classifyKeywordsInGenerics) {
|
||||
// If it looks like we're could be in something generic, don't classify this
|
||||
// as a keyword. We may just get overwritten by the syntactic classifier,
|
||||
// causing a noisy experience for the user.
|
||||
token = SyntaxKind.Identifier;
|
||||
}
|
||||
if (angleBracketStack > 0 && !syntacticClassifierAbsent) {
|
||||
// If it looks like we're could be in something generic, don't classify this
|
||||
// as a keyword. We may just get overwritten by the syntactic classifier,
|
||||
// causing a noisy experience for the user.
|
||||
token = SyntaxKind.Identifier;
|
||||
}
|
||||
}
|
||||
else if (token === SyntaxKind.TemplateHead) {
|
||||
templateStack.push(token);
|
||||
}
|
||||
else if (token === SyntaxKind.OpenBraceToken) {
|
||||
// If we don't have anything on the template stack,
|
||||
// then we aren't trying to keep track of a previously scanned template head.
|
||||
if (templateStack.length > 0) {
|
||||
templateStack.push(token);
|
||||
}
|
||||
}
|
||||
else if (token === SyntaxKind.CloseBraceToken) {
|
||||
// If we don't have anything on the template stack,
|
||||
// then we aren't trying to keep track of a previously scanned template head.
|
||||
if (templateStack.length > 0) {
|
||||
var lastTemplateStackToken = lastOrUndefined(templateStack);
|
||||
|
||||
if (lastTemplateStackToken === SyntaxKind.TemplateHead) {
|
||||
token = scanner.reScanTemplateToken();
|
||||
|
||||
// Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us.
|
||||
if (token === SyntaxKind.TemplateTail) {
|
||||
templateStack.pop();
|
||||
}
|
||||
else {
|
||||
Debug.assert(token === SyntaxKind.TemplateMiddle, "Should have been a template middle. Was " + token);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.assert(lastTemplateStackToken === SyntaxKind.OpenBraceToken, "Should have been an open brace. Was: " + token);
|
||||
templateStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastNonTriviaToken = token;
|
||||
@@ -5789,6 +5883,22 @@ module ts {
|
||||
result.finalLexState = EndOfLineState.InMultiLineCommentTrivia;
|
||||
}
|
||||
}
|
||||
else if (isTemplateLiteralKind(token)) {
|
||||
if (scanner.isUnterminated()) {
|
||||
if (token === SyntaxKind.TemplateTail) {
|
||||
result.finalLexState = EndOfLineState.InTemplateMiddleOrTail;
|
||||
}
|
||||
else if (token === SyntaxKind.NoSubstitutionTemplateLiteral) {
|
||||
result.finalLexState = EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate;
|
||||
}
|
||||
else {
|
||||
Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (templateStack.length > 0 && lastOrUndefined(templateStack) === SyntaxKind.TemplateHead) {
|
||||
result.finalLexState = EndOfLineState.InTemplateSubstitutionPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5892,6 +6002,9 @@ module ts {
|
||||
return TokenClass.Whitespace;
|
||||
case SyntaxKind.Identifier:
|
||||
default:
|
||||
if (isTemplateLiteralKind(token)) {
|
||||
return TokenClass.StringLiteral;
|
||||
}
|
||||
return TokenClass.Identifier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ module ts {
|
||||
}
|
||||
|
||||
export interface ClassifierShim extends Shim {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): string;
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string;
|
||||
}
|
||||
|
||||
export interface CoreServicesShim extends Shim {
|
||||
|
||||
@@ -1741,6 +1741,9 @@ declare module "typescript" {
|
||||
InMultiLineCommentTrivia = 1,
|
||||
InSingleQuoteStringLiteral = 2,
|
||||
InDoubleQuoteStringLiteral = 3,
|
||||
InTemplateHeadOrNoSubstitutionTemplate = 4,
|
||||
InTemplateMiddleOrTail = 5,
|
||||
InTemplateSubstitutionPosition = 6,
|
||||
}
|
||||
enum TokenClass {
|
||||
Punctuation = 0,
|
||||
@@ -1762,7 +1765,26 @@ declare module "typescript" {
|
||||
classification: TokenClass;
|
||||
}
|
||||
interface Classifier {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
/**
|
||||
* Gives lexical classifications of tokens on a line without any syntactic context.
|
||||
* For instance, a token consisting of the text 'string' can be either an identifier
|
||||
* named 'string' or the keyword 'string', however, because this classifier is not aware,
|
||||
* it relies on certain heuristics to give acceptable results. For classifications where
|
||||
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
|
||||
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
|
||||
* lexical, syntactic, and semantic classifiers may issue the best user experience.
|
||||
*
|
||||
* @param text The text of a line to classify.
|
||||
* @param lexState The state of the lexical classifier at the end of the previous line.
|
||||
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
|
||||
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
|
||||
* certain heuristics may be used in its place; however, if there is a
|
||||
* syntactic classifier (syntacticClassifierAbsent=false), certain
|
||||
* classifications which may be incorrectly categorized will be given
|
||||
* back as Identifiers in order to allow the syntactic classifier to
|
||||
* subsume the classification.
|
||||
*/
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
|
||||
}
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
|
||||
@@ -5539,6 +5539,15 @@ declare module "typescript" {
|
||||
>SourceFile : SourceFile
|
||||
|
||||
getDefaultLibFileName(options: CompilerOptions): string;
|
||||
|
||||
>getDefaultLibFileName : (options: CompilerOptions) => string
|
||||
>options : CompilerOptions
|
||||
>CompilerOptions : CompilerOptions
|
||||
|
||||
getCancellationToken?(): CancellationToken;
|
||||
|
||||
>getCancellationToken : () => CancellationToken
|
||||
>CancellationToken : CancellationToken
|
||||
|
||||
writeFile: WriteFileCallback;
|
||||
|
||||
@@ -5594,12 +5603,31 @@ declare module "typescript" {
|
||||
|
||||
declare module "typescript" {
|
||||
|
||||
newLength: number;
|
||||
|
||||
interface ErrorCallback {
|
||||
|
||||
>ErrorCallback : ErrorCallback
|
||||
|
||||
(message: DiagnosticMessage, length: number): void;
|
||||
|
||||
>message : DiagnosticMessage
|
||||
>DiagnosticMessage : DiagnosticMessage
|
||||
>length : number
|
||||
}
|
||||
|
||||
interface Scanner {
|
||||
|
||||
>Scanner : Scanner
|
||||
|
||||
getStartPos(): number;
|
||||
|
||||
>getStartPos : () => number
|
||||
|
||||
getToken(): SyntaxKind;
|
||||
|
||||
>getToken : () => SyntaxKind
|
||||
>SyntaxKind : SyntaxKind
|
||||
|
||||
}
|
||||
getTextPos(): number;
|
||||
|
||||
>getTextPos : () => number
|
||||
|
||||
|
||||
@@ -1772,6 +1772,9 @@ declare module "typescript" {
|
||||
InMultiLineCommentTrivia = 1,
|
||||
InSingleQuoteStringLiteral = 2,
|
||||
InDoubleQuoteStringLiteral = 3,
|
||||
InTemplateHeadOrNoSubstitutionTemplate = 4,
|
||||
InTemplateMiddleOrTail = 5,
|
||||
InTemplateSubstitutionPosition = 6,
|
||||
}
|
||||
enum TokenClass {
|
||||
Punctuation = 0,
|
||||
@@ -1793,7 +1796,26 @@ declare module "typescript" {
|
||||
classification: TokenClass;
|
||||
}
|
||||
interface Classifier {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
/**
|
||||
* Gives lexical classifications of tokens on a line without any syntactic context.
|
||||
* For instance, a token consisting of the text 'string' can be either an identifier
|
||||
* named 'string' or the keyword 'string', however, because this classifier is not aware,
|
||||
* it relies on certain heuristics to give acceptable results. For classifications where
|
||||
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
|
||||
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
|
||||
* lexical, syntactic, and semantic classifiers may issue the best user experience.
|
||||
*
|
||||
* @param text The text of a line to classify.
|
||||
* @param lexState The state of the lexical classifier at the end of the previous line.
|
||||
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
|
||||
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
|
||||
* certain heuristics may be used in its place; however, if there is a
|
||||
* syntactic classifier (syntacticClassifierAbsent=false), certain
|
||||
* classifications which may be incorrectly categorized will be given
|
||||
* back as Identifiers in order to allow the syntactic classifier to
|
||||
* subsume the classification.
|
||||
*/
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
|
||||
}
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
|
||||
@@ -5683,6 +5683,15 @@ declare module "typescript" {
|
||||
>SourceFile : SourceFile
|
||||
|
||||
getDefaultLibFileName(options: CompilerOptions): string;
|
||||
|
||||
>getDefaultLibFileName : (options: CompilerOptions) => string
|
||||
>options : CompilerOptions
|
||||
>CompilerOptions : CompilerOptions
|
||||
|
||||
getCancellationToken?(): CancellationToken;
|
||||
|
||||
>getCancellationToken : () => CancellationToken
|
||||
>CancellationToken : CancellationToken
|
||||
|
||||
writeFile: WriteFileCallback;
|
||||
|
||||
@@ -5738,12 +5747,31 @@ declare module "typescript" {
|
||||
|
||||
declare module "typescript" {
|
||||
|
||||
newLength: number;
|
||||
|
||||
interface ErrorCallback {
|
||||
|
||||
>ErrorCallback : ErrorCallback
|
||||
|
||||
(message: DiagnosticMessage, length: number): void;
|
||||
|
||||
>message : DiagnosticMessage
|
||||
>DiagnosticMessage : DiagnosticMessage
|
||||
>length : number
|
||||
}
|
||||
|
||||
interface Scanner {
|
||||
|
||||
>Scanner : Scanner
|
||||
|
||||
getStartPos(): number;
|
||||
|
||||
>getStartPos : () => number
|
||||
|
||||
getToken(): SyntaxKind;
|
||||
|
||||
>getToken : () => SyntaxKind
|
||||
>SyntaxKind : SyntaxKind
|
||||
|
||||
}
|
||||
getTextPos(): number;
|
||||
|
||||
>getTextPos : () => number
|
||||
|
||||
|
||||
@@ -1773,6 +1773,9 @@ declare module "typescript" {
|
||||
InMultiLineCommentTrivia = 1,
|
||||
InSingleQuoteStringLiteral = 2,
|
||||
InDoubleQuoteStringLiteral = 3,
|
||||
InTemplateHeadOrNoSubstitutionTemplate = 4,
|
||||
InTemplateMiddleOrTail = 5,
|
||||
InTemplateSubstitutionPosition = 6,
|
||||
}
|
||||
enum TokenClass {
|
||||
Punctuation = 0,
|
||||
@@ -1794,7 +1797,26 @@ declare module "typescript" {
|
||||
classification: TokenClass;
|
||||
}
|
||||
interface Classifier {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
/**
|
||||
* Gives lexical classifications of tokens on a line without any syntactic context.
|
||||
* For instance, a token consisting of the text 'string' can be either an identifier
|
||||
* named 'string' or the keyword 'string', however, because this classifier is not aware,
|
||||
* it relies on certain heuristics to give acceptable results. For classifications where
|
||||
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
|
||||
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
|
||||
* lexical, syntactic, and semantic classifiers may issue the best user experience.
|
||||
*
|
||||
* @param text The text of a line to classify.
|
||||
* @param lexState The state of the lexical classifier at the end of the previous line.
|
||||
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
|
||||
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
|
||||
* certain heuristics may be used in its place; however, if there is a
|
||||
* syntactic classifier (syntacticClassifierAbsent=false), certain
|
||||
* classifications which may be incorrectly categorized will be given
|
||||
* back as Identifiers in order to allow the syntactic classifier to
|
||||
* subsume the classification.
|
||||
*/
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
|
||||
}
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
|
||||
@@ -5635,6 +5635,15 @@ declare module "typescript" {
|
||||
|
||||
InDoubleQuoteStringLiteral = 3,
|
||||
>InDoubleQuoteStringLiteral : EndOfLineState
|
||||
|
||||
InTemplateHeadOrNoSubstitutionTemplate = 4,
|
||||
>InTemplateHeadOrNoSubstitutionTemplate : EndOfLineState
|
||||
|
||||
InTemplateMiddleOrTail = 5,
|
||||
>InTemplateMiddleOrTail : EndOfLineState
|
||||
|
||||
InTemplateSubstitutionPosition = 6,
|
||||
>InTemplateSubstitutionPosition : EndOfLineState
|
||||
}
|
||||
enum TokenClass {
|
||||
>TokenClass : TokenClass
|
||||
@@ -5690,12 +5699,31 @@ declare module "typescript" {
|
||||
interface Classifier {
|
||||
>Classifier : Classifier
|
||||
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
>getClassificationsForLine : (text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean) => ClassificationResult
|
||||
/**
|
||||
* Gives lexical classifications of tokens on a line without any syntactic context.
|
||||
* For instance, a token consisting of the text 'string' can be either an identifier
|
||||
* named 'string' or the keyword 'string', however, because this classifier is not aware,
|
||||
* it relies on certain heuristics to give acceptable results. For classifications where
|
||||
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
|
||||
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
|
||||
* lexical, syntactic, and semantic classifiers may issue the best user experience.
|
||||
*
|
||||
* @param text The text of a line to classify.
|
||||
* @param lexState The state of the lexical classifier at the end of the previous line.
|
||||
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
|
||||
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
|
||||
* certain heuristics may be used in its place; however, if there is a
|
||||
* syntactic classifier (syntacticClassifierAbsent=false), certain
|
||||
* classifications which may be incorrectly categorized will be given
|
||||
* back as Identifiers in order to allow the syntactic classifier to
|
||||
* subsume the classification.
|
||||
*/
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
|
||||
>getClassificationsForLine : (text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean) => ClassificationResult
|
||||
>text : string
|
||||
>lexState : EndOfLineState
|
||||
>EndOfLineState : EndOfLineState
|
||||
>classifyKeywordsInGenerics : boolean
|
||||
>syntacticClassifierAbsent : boolean
|
||||
>ClassificationResult : ClassificationResult
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -1810,6 +1810,9 @@ declare module "typescript" {
|
||||
InMultiLineCommentTrivia = 1,
|
||||
InSingleQuoteStringLiteral = 2,
|
||||
InDoubleQuoteStringLiteral = 3,
|
||||
InTemplateHeadOrNoSubstitutionTemplate = 4,
|
||||
InTemplateMiddleOrTail = 5,
|
||||
InTemplateSubstitutionPosition = 6,
|
||||
}
|
||||
enum TokenClass {
|
||||
Punctuation = 0,
|
||||
@@ -1831,7 +1834,26 @@ declare module "typescript" {
|
||||
classification: TokenClass;
|
||||
}
|
||||
interface Classifier {
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
/**
|
||||
* Gives lexical classifications of tokens on a line without any syntactic context.
|
||||
* For instance, a token consisting of the text 'string' can be either an identifier
|
||||
* named 'string' or the keyword 'string', however, because this classifier is not aware,
|
||||
* it relies on certain heuristics to give acceptable results. For classifications where
|
||||
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
|
||||
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
|
||||
* lexical, syntactic, and semantic classifiers may issue the best user experience.
|
||||
*
|
||||
* @param text The text of a line to classify.
|
||||
* @param lexState The state of the lexical classifier at the end of the previous line.
|
||||
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
|
||||
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
|
||||
* certain heuristics may be used in its place; however, if there is a
|
||||
* syntactic classifier (syntacticClassifierAbsent=false), certain
|
||||
* classifications which may be incorrectly categorized will be given
|
||||
* back as Identifiers in order to allow the syntactic classifier to
|
||||
* subsume the classification.
|
||||
*/
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
|
||||
}
|
||||
/**
|
||||
* The document registry represents a store of SourceFile objects that can be shared between
|
||||
|
||||
@@ -5808,6 +5808,15 @@ declare module "typescript" {
|
||||
|
||||
InDoubleQuoteStringLiteral = 3,
|
||||
>InDoubleQuoteStringLiteral : EndOfLineState
|
||||
|
||||
InTemplateHeadOrNoSubstitutionTemplate = 4,
|
||||
>InTemplateHeadOrNoSubstitutionTemplate : EndOfLineState
|
||||
|
||||
InTemplateMiddleOrTail = 5,
|
||||
>InTemplateMiddleOrTail : EndOfLineState
|
||||
|
||||
InTemplateSubstitutionPosition = 6,
|
||||
>InTemplateSubstitutionPosition : EndOfLineState
|
||||
}
|
||||
enum TokenClass {
|
||||
>TokenClass : TokenClass
|
||||
@@ -5863,12 +5872,31 @@ declare module "typescript" {
|
||||
interface Classifier {
|
||||
>Classifier : Classifier
|
||||
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): ClassificationResult;
|
||||
>getClassificationsForLine : (text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean) => ClassificationResult
|
||||
/**
|
||||
* Gives lexical classifications of tokens on a line without any syntactic context.
|
||||
* For instance, a token consisting of the text 'string' can be either an identifier
|
||||
* named 'string' or the keyword 'string', however, because this classifier is not aware,
|
||||
* it relies on certain heuristics to give acceptable results. For classifications where
|
||||
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
|
||||
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
|
||||
* lexical, syntactic, and semantic classifiers may issue the best user experience.
|
||||
*
|
||||
* @param text The text of a line to classify.
|
||||
* @param lexState The state of the lexical classifier at the end of the previous line.
|
||||
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
|
||||
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
|
||||
* certain heuristics may be used in its place; however, if there is a
|
||||
* syntactic classifier (syntacticClassifierAbsent=false), certain
|
||||
* classifications which may be incorrectly categorized will be given
|
||||
* back as Identifiers in order to allow the syntactic classifier to
|
||||
* subsume the classification.
|
||||
*/
|
||||
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
|
||||
>getClassificationsForLine : (text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean) => ClassificationResult
|
||||
>text : string
|
||||
>lexState : EndOfLineState
|
||||
>EndOfLineState : EndOfLineState
|
||||
>classifyKeywordsInGenerics : boolean
|
||||
>syntacticClassifierAbsent : boolean
|
||||
>ClassificationResult : ClassificationResult
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(7,9): error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(15,13): error TS2451: Cannot redeclare block-scoped variable 'y'.
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(22,7): error TS2451: Cannot redeclare block-scoped variable 'z'.
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(7,9): error TS4090: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(15,13): error TS4090: Cannot initialize outer scoped variable 'y' in the same scope as block scoped declaration 'y'.
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(22,7): error TS4090: Cannot initialize outer scoped variable 'z' in the same scope as block scoped declaration 'z'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts (3 errors) ====
|
||||
@@ -12,7 +12,7 @@ tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(22,7): error TS
|
||||
|
||||
var x = 0;
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
!!! error TS4090: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(22,7): error TS
|
||||
{
|
||||
var y = 0;
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'y'.
|
||||
!!! error TS4090: Cannot initialize outer scoped variable 'y' in the same scope as block scoped declaration 'y'.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,5 +31,5 @@ tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(22,7): error TS
|
||||
const z = 0;
|
||||
var z = 0
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'z'.
|
||||
!!! error TS4090: Cannot initialize outer scoped variable 'z' in the same scope as block scoped declaration 'z'.
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(2,5): error TS2451: Cannot redeclare block-scoped variable 'e0'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(3,5): error TS2451: Cannot redeclare block-scoped variable 'e0'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(4,10): error TS2451: Cannot redeclare block-scoped variable 'e0'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(7,9): error TS2451: Cannot redeclare block-scoped variable 'x1'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(8,9): error TS2451: Cannot redeclare block-scoped variable 'x1'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(9,14): error TS2451: Cannot redeclare block-scoped variable 'x1'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(13,9): error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(15,13): error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(18,18): error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(23,9): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(24,9): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(25,14): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(29,9): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(31,13): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(34,18): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(38,5): error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(39,10): error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(43,9): error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(44,14): error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(49,9): error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
tests/cases/compiler/letAndVarRedeclaration.ts(50,14): error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/letAndVarRedeclaration.ts (21 errors) ====
|
||||
|
||||
let e0
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'e0'.
|
||||
var e0;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'e0'.
|
||||
function e0() { }
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'e0'.
|
||||
|
||||
function f0() {
|
||||
let x1;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x1'.
|
||||
var x1;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x1'.
|
||||
function x1() { }
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x1'.
|
||||
}
|
||||
|
||||
function f1() {
|
||||
let x;
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
{
|
||||
var x;
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
}
|
||||
{
|
||||
function x() { }
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x'.
|
||||
}
|
||||
}
|
||||
|
||||
module M0 {
|
||||
let x2;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
var x2;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
function x2() { }
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
}
|
||||
|
||||
module M1 {
|
||||
let x2;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
{
|
||||
var x2;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
}
|
||||
{
|
||||
function x2() { }
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
}
|
||||
}
|
||||
|
||||
let x11;
|
||||
~~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
for (var x11; ;) {
|
||||
~~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let x11;
|
||||
~~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
for (var x11; ;) {
|
||||
~~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
}
|
||||
}
|
||||
|
||||
module M2 {
|
||||
let x11;
|
||||
~~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
for (var x11; ;) {
|
||||
~~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x11'.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
//// [letAndVarRedeclaration.ts]
|
||||
|
||||
let e0
|
||||
var e0;
|
||||
function e0() { }
|
||||
|
||||
function f0() {
|
||||
let x1;
|
||||
var x1;
|
||||
function x1() { }
|
||||
}
|
||||
|
||||
function f1() {
|
||||
let x;
|
||||
{
|
||||
var x;
|
||||
}
|
||||
{
|
||||
function x() { }
|
||||
}
|
||||
}
|
||||
|
||||
module M0 {
|
||||
let x2;
|
||||
var x2;
|
||||
function x2() { }
|
||||
}
|
||||
|
||||
module M1 {
|
||||
let x2;
|
||||
{
|
||||
var x2;
|
||||
}
|
||||
{
|
||||
function x2() { }
|
||||
}
|
||||
}
|
||||
|
||||
let x11;
|
||||
for (var x11; ;) {
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let x11;
|
||||
for (var x11; ;) {
|
||||
}
|
||||
}
|
||||
|
||||
module M2 {
|
||||
let x11;
|
||||
for (var x11; ;) {
|
||||
}
|
||||
}
|
||||
|
||||
//// [letAndVarRedeclaration.js]
|
||||
let e0;
|
||||
var e0;
|
||||
function e0() { }
|
||||
function f0() {
|
||||
let x1;
|
||||
var x1;
|
||||
function x1() { }
|
||||
}
|
||||
function f1() {
|
||||
let x;
|
||||
{
|
||||
var x;
|
||||
}
|
||||
{
|
||||
function x() { }
|
||||
}
|
||||
}
|
||||
var M0;
|
||||
(function (M0) {
|
||||
let x2;
|
||||
var x2;
|
||||
function x2() { }
|
||||
})(M0 || (M0 = {}));
|
||||
var M1;
|
||||
(function (M1) {
|
||||
let x2;
|
||||
{
|
||||
var x2;
|
||||
}
|
||||
{
|
||||
function x2() { }
|
||||
}
|
||||
})(M1 || (M1 = {}));
|
||||
let x11;
|
||||
for (var x11;;) {
|
||||
}
|
||||
function f2() {
|
||||
let x11;
|
||||
for (var x11;;) {
|
||||
}
|
||||
}
|
||||
var M2;
|
||||
(function (M2) {
|
||||
let x11;
|
||||
for (var x11;;) {
|
||||
}
|
||||
})(M2 || (M2 = {}));
|
||||
@@ -0,0 +1,30 @@
|
||||
tests/cases/compiler/shadowingViaLocalValue.ts(2,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
|
||||
tests/cases/compiler/shadowingViaLocalValue.ts(4,13): error TS4090: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
tests/cases/compiler/shadowingViaLocalValue.ts(9,5): error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
|
||||
tests/cases/compiler/shadowingViaLocalValue.ts(11,18): error TS4090: Cannot initialize outer scoped variable 'x1' in the same scope as block scoped declaration 'x1'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/shadowingViaLocalValue.ts (4 errors) ====
|
||||
{
|
||||
let x;
|
||||
~~~
|
||||
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
|
||||
{
|
||||
var x = 1;
|
||||
~
|
||||
!!! error TS4090: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let x1;
|
||||
~~~
|
||||
!!! error TS1153: 'let' declarations are only available when targeting ECMAScript 6 and higher.
|
||||
{
|
||||
for (var x1 = 0; ;);
|
||||
~~
|
||||
!!! error TS4090: Cannot initialize outer scoped variable 'x1' in the same scope as block scoped declaration 'x1'.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
//// [shadowingViaLocalValue.ts]
|
||||
{
|
||||
let x;
|
||||
{
|
||||
var x = 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let x1;
|
||||
{
|
||||
for (var x1 = 0; ;);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//// [shadowingViaLocalValue.js]
|
||||
{
|
||||
let x;
|
||||
{
|
||||
var x = 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
let x1;
|
||||
{
|
||||
for (var x1 = 0;;)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// @target: es6
|
||||
|
||||
let e0
|
||||
var e0;
|
||||
function e0() { }
|
||||
|
||||
function f0() {
|
||||
let x1;
|
||||
var x1;
|
||||
function x1() { }
|
||||
}
|
||||
|
||||
function f1() {
|
||||
let x;
|
||||
{
|
||||
var x;
|
||||
}
|
||||
{
|
||||
function x() { }
|
||||
}
|
||||
}
|
||||
|
||||
module M0 {
|
||||
let x2;
|
||||
var x2;
|
||||
function x2() { }
|
||||
}
|
||||
|
||||
module M1 {
|
||||
let x2;
|
||||
{
|
||||
var x2;
|
||||
}
|
||||
{
|
||||
function x2() { }
|
||||
}
|
||||
}
|
||||
|
||||
let x11;
|
||||
for (var x11; ;) {
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let x11;
|
||||
for (var x11; ;) {
|
||||
}
|
||||
}
|
||||
|
||||
module M2 {
|
||||
let x11;
|
||||
for (var x11; ;) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
let x;
|
||||
{
|
||||
var x = 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let x1;
|
||||
{
|
||||
for (var x1 = 0; ;);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
interface ClassificationEntry {
|
||||
value: any;
|
||||
classification: ts.TokenClass;
|
||||
position?: number;
|
||||
}
|
||||
|
||||
describe('Colorization', function () {
|
||||
@@ -23,16 +24,23 @@ describe('Colorization', function () {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function punctuation(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.Punctuation }; }
|
||||
function keyword(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.Keyword }; }
|
||||
function operator(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.Operator }; }
|
||||
function comment(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.Comment }; }
|
||||
function whitespace(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.Whitespace }; }
|
||||
function identifier(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.Identifier }; }
|
||||
function numberLiteral(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.NumberLiteral }; }
|
||||
function stringLiteral(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.StringLiteral }; }
|
||||
function regExpLiteral(text: string): ClassificationEntry { return { value: text, classification: ts.TokenClass.RegExpLiteral }; }
|
||||
function finalEndOfLineState(value: number): ClassificationEntry { return { value: value, classification: <ts.TokenClass>undefined }; }
|
||||
function punctuation(text: string, position?: number) { return createClassification(text, ts.TokenClass.Punctuation, position); }
|
||||
function keyword(text: string, position?: number) { return createClassification(text, ts.TokenClass.Keyword, position); }
|
||||
function operator(text: string, position?: number) { return createClassification(text, ts.TokenClass.Operator, position); }
|
||||
function comment(text: string, position?: number) { return createClassification(text, ts.TokenClass.Comment, position); }
|
||||
function whitespace(text: string, position?: number) { return createClassification(text, ts.TokenClass.Whitespace, position); }
|
||||
function identifier(text: string, position?: number) { return createClassification(text, ts.TokenClass.Identifier, position); }
|
||||
function numberLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.NumberLiteral, position); }
|
||||
function stringLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.StringLiteral, position); }
|
||||
function regExpLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.RegExpLiteral, position); }
|
||||
function finalEndOfLineState(value: number): ClassificationEntry { return { value: value, classification: undefined, position: 0 }; }
|
||||
function createClassification(text: string, tokenClass: ts.TokenClass, position?: number): ClassificationEntry {
|
||||
return {
|
||||
value: text,
|
||||
classification: tokenClass,
|
||||
position: position,
|
||||
};
|
||||
}
|
||||
|
||||
function testLexicalClassification(text: string, initialEndOfLineState: ts.EndOfLineState, ...expectedEntries: ClassificationEntry[]): void {
|
||||
var result = classifier.getClassificationsForLine(text, initialEndOfLineState);
|
||||
@@ -44,7 +52,7 @@ describe('Colorization', function () {
|
||||
assert.equal(result.finalLexState, expectedEntry.value, "final endOfLineState does not match expected.");
|
||||
}
|
||||
else {
|
||||
var actualEntryPosition = text.indexOf(expectedEntry.value);
|
||||
var actualEntryPosition = expectedEntry.position !== undefined ? expectedEntry.position : text.indexOf(expectedEntry.value);
|
||||
assert(actualEntryPosition >= 0, "token: '" + expectedEntry.value + "' does not exit in text: '" + text + "'.");
|
||||
|
||||
var actualEntry = getEntryAtPosistion(result, actualEntryPosition);
|
||||
@@ -254,6 +262,106 @@ describe('Colorization', function () {
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
|
||||
it("classifies a single line no substitution template string correctly", () => {
|
||||
testLexicalClassification("`number number public string`",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("`number number public string`"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
it("classifies substitution parts of a template string correctly", () => {
|
||||
testLexicalClassification("`number '${ 1 + 1 }' string '${ 'hello' }'`",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("`number '${"),
|
||||
numberLiteral("1"),
|
||||
operator("+"),
|
||||
numberLiteral("1"),
|
||||
stringLiteral("}' string '${"),
|
||||
stringLiteral("'hello'"),
|
||||
stringLiteral("}'`"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
it("classifies an unterminated no substitution template string correctly", () => {
|
||||
testLexicalClassification("`hello world",
|
||||
ts.EndOfLineState.Start,
|
||||
stringLiteral("`hello world"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate));
|
||||
});
|
||||
it("classifies the entire line of an unterminated multiline no-substitution/head template", () => {
|
||||
testLexicalClassification("...",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
stringLiteral("..."),
|
||||
finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate));
|
||||
});
|
||||
it("classifies the entire line of an unterminated multiline template middle/end",() => {
|
||||
testLexicalClassification("...",
|
||||
ts.EndOfLineState.InTemplateMiddleOrTail,
|
||||
stringLiteral("..."),
|
||||
finalEndOfLineState(ts.EndOfLineState.InTemplateMiddleOrTail));
|
||||
});
|
||||
it("classifies a termination of a multiline template head", () => {
|
||||
testLexicalClassification("...${",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
stringLiteral("...${"),
|
||||
finalEndOfLineState(ts.EndOfLineState.InTemplateSubstitutionPosition));
|
||||
});
|
||||
it("classifies the termination of a multiline no substitution template", () => {
|
||||
testLexicalClassification("...`",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
stringLiteral("...`"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
it("classifies the substitution parts and middle/tail of a multiline template string", () => {
|
||||
testLexicalClassification("${ 1 + 1 }...`",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
stringLiteral("${"),
|
||||
numberLiteral("1"),
|
||||
operator("+"),
|
||||
numberLiteral("1"),
|
||||
stringLiteral("}...`"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
it("classifies a template middle and propagates the end of line state",() => {
|
||||
testLexicalClassification("${ 1 + 1 }...`",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
stringLiteral("${"),
|
||||
numberLiteral("1"),
|
||||
operator("+"),
|
||||
numberLiteral("1"),
|
||||
stringLiteral("}...`"),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
});
|
||||
it("classifies substitution expressions with curly braces appropriately", () => {
|
||||
var pos = 0;
|
||||
var lastLength = 0;
|
||||
|
||||
testLexicalClassification("...${ () => { } } ${ { x: `1` } }...`",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
stringLiteral(track("...${"), pos),
|
||||
punctuation(track(" ", "("), pos),
|
||||
punctuation(track(")"), pos),
|
||||
punctuation(track(" ", "=>"), pos),
|
||||
punctuation(track(" ", "{"), pos),
|
||||
punctuation(track(" ", "}"), pos),
|
||||
stringLiteral(track(" ", "} ${"), pos),
|
||||
punctuation(track(" ", "{"), pos),
|
||||
identifier(track(" ", "x"), pos),
|
||||
punctuation(track(":"), pos),
|
||||
stringLiteral(track(" ", "`1`"), pos),
|
||||
punctuation(track(" ", "}"), pos),
|
||||
stringLiteral(track(" ", "}...`"), pos),
|
||||
finalEndOfLineState(ts.EndOfLineState.Start));
|
||||
|
||||
// Adjusts 'pos' by accounting for the length of each portion of the string,
|
||||
// but only return the last given string
|
||||
function track(...vals: string[]): string {
|
||||
for (var i = 0, n = vals.length; i < n; i++) {
|
||||
pos += lastLength;
|
||||
lastLength = vals[i].length;
|
||||
}
|
||||
return ts.lastOrUndefined(vals);
|
||||
}
|
||||
});
|
||||
|
||||
it("classifies partially written generics correctly.", function () {
|
||||
testLexicalClassification("Foo<number",
|
||||
ts.EndOfLineState.Start,
|
||||
|
||||
Reference in New Issue
Block a user