1/* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import * as ts from "typescript"; 17import { CmdOptions } from "./cmdOptions"; 18import { 19 DiagnosticCode, 20 DiagnosticError 21} from "./diagnostic"; 22import { hasExportKeywordModifier } from "./base/util"; 23import { findInnerExprOfParenthesis } from "./expression/parenthesizedExpression"; 24import * as jshelpers from "./jshelpers"; 25import { getContainingFunctionDeclaration, getSourceFileOfNode } from "./jshelpers"; 26import { LOGE } from "./log"; 27import { Recorder } from "./recorder"; 28import { 29 CatchParameter, 30 ClassDecl, 31 ConstDecl, 32 Decl, 33 FuncDecl, 34 FunctionScope, 35 GlobalScope, 36 LetDecl, 37 LocalScope, 38 ModuleScope, 39 Scope, 40 VarDecl 41} from "./scope"; 42import { isStrictMode } from "./strictMode"; 43import { checkSyntaxErrorForStrictMode } from "./syntaxCheckerForStrcitMode"; 44import { 45 allowLetAndConstDeclarations, 46 isAssignmentOperator, 47 isBindingPattern, 48 isDeclInGlobal, 49 isFunctionLikeDeclaration, 50 isGlobalIdentifier, 51 isOptionalParameter, 52 isStatement, 53 visibilityToString, 54 isInBlockScope 55} from "./syntaxCheckHelper"; 56import { MandatoryArguments } from "./variable"; 57 58//*************************************Part 1: Implement early check of declarations*******************************// 59export function checkDuplicateDeclaration(recorder: Recorder) { 60 let scopeMap = recorder.getScopeMap(); 61 scopeMap.forEach((scope, node) => { 62 // implement functionParameter-related duplicate-entry check 63 if (isFunctionLikeDeclaration(node)) { 64 if (isStrictMode(node)) { 65 checkDuplicateParameter(node, recorder); 66 } 67 68 if (node.body) { 69 let bodyScope = <Scope>scopeMap.get(node.body); 70 let parameterNames = getParameterNames(node, recorder); 71 if (bodyScope) { 72 checkDuplicateParameterVar(parameterNames, bodyScope); 73 } 74 } 75 } 76 77 // implement catchParameter-related duplicate-entry check 78 if ((node.kind == ts.SyntaxKind.Block) && (node.parent != undefined && node.parent.kind == ts.SyntaxKind.CatchClause)) { 79 let catchScope = <Scope>scopeMap.get(node.parent); 80 checkDuplicateInCatch(scope, catchScope); 81 } 82 83 let decls = scope.getDecls(); 84 let exportFuncMap: Map<string, boolean> = new Map<string, boolean>(); 85 for (let i = 0; i < decls.length; i++) { 86 checkDeclareGlobalId(decls[i], scope); 87 checkDuplicateEntryInScope(scope, i); 88 checkDuplicateEntryAcrossScope(scope, i); 89 if (ts.isFunctionDeclaration(decls[i].node) && scope instanceof ModuleScope) { 90 hasDuplicateExportedFuncDecl(<FuncDecl>decls[i], exportFuncMap); 91 } 92 } 93 }) 94} 95 96function checkDuplicateEntryAcrossScope(scope: Scope, index: number) { 97 let decls = scope.getDecls(); 98 let parentScope: Scope | undefined = scope; 99 if (decls[index] instanceof VarDecl) { 100 while (!(parentScope instanceof FunctionScope)) { 101 parentScope = parentScope.getParent(); 102 if (!parentScope) { 103 return; 104 } 105 106 let parentDecls = parentScope.getDecls(); 107 parentDecls.forEach(parentDecl => { 108 if (hasDuplicateEntryAcrossScope(decls[index], parentDecl)) { 109 throwDupIdError(decls[index]); 110 } 111 }); 112 } 113 } 114} 115 116function checkDuplicateEntryInScope(scope: Scope, index: number) { 117 let decls = scope.getDecls(); 118 for (let i = index + 1; i < decls.length; i++) { 119 if (hasDuplicateEntryInScope(decls[index], decls[i], scope)) { 120 throwDupIdError(decls[i]); 121 } 122 } 123} 124 125function hasDuplicateExportedFuncDecl(decl: FuncDecl, exportFuncMap: Map<string, boolean>) { 126 if (!exportFuncMap.has(decl.name)) { 127 exportFuncMap.set(decl.name, hasExportKeywordModifier(decl.node)); 128 } else { 129 if (exportFuncMap.get(decl.name) == true || hasExportKeywordModifier(decl.node)) { 130 throw new DiagnosticError(decl.node, DiagnosticCode.Duplicate_identifier_0, jshelpers.getSourceFileOfNode(decl.node), [decl.name]); 131 } 132 } 133} 134 135function hasDuplicateEntryAcrossScope(decl1: Decl, decl2: Decl) { 136 if ((decl2 instanceof LetDecl) || (decl2 instanceof ConstDecl)) { 137 return decl1.name == decl2.name; 138 } 139} 140 141function hasDuplicateEntryInScope(decl1: Decl, decl2: Decl, scope: Scope) { 142 if (((decl1 instanceof LetDecl) || (decl1 instanceof ConstDecl) || (decl1 instanceof ClassDecl && ts.isClassDeclaration(decl1.node)) || 143 (decl2 instanceof LetDecl) || (decl2 instanceof ConstDecl) || (decl2 instanceof ClassDecl && ts.isClassDeclaration(decl1.node))) && 144 !ts.isClassExpression(decl1.node) && !ts.isClassExpression(decl2.node)) { 145 return decl1.name == decl2.name; 146 } 147 // Var and FunctionDeclaration with same names, FunctionDeclaration and FunctionDeclaration with same names are illegal in strict mode 148 // and Module 149 /** 150 * eg1. 151 * if (true) { 152 * var a; 153 * function a() {}; 154 * } 155 * 156 * eg2. 157 * if (true) { 158 * function a() {}; 159 * function a() {}; 160 * } 161 * eg3. [module] 162 * var a; 163 * function a(){}; 164 */ 165 if (scope instanceof LocalScope && isStrictMode(decl1.node) || scope instanceof ModuleScope) { 166 if (decl1 instanceof FuncDecl || decl2 instanceof FuncDecl) { 167 if (isFunctionLikeDeclaration(decl1.node.parent.parent) || isFunctionLikeDeclaration(decl2.node.parent.parent)) { 168 return false; 169 } 170 return decl1.name == decl2.name; 171 } 172 } 173 174 return false; 175} 176 177function checkDuplicateInCatch(blockScope: Scope, catchScope: Scope) { 178 let bodyDecls = blockScope.getDecls(); 179 let catchParameters = catchScope.getDecls(); 180 181 for (let i = 0; i < catchParameters.length; i++) { 182 for (let j = i + 1; j < catchParameters.length; j++) { 183 if (catchParameters[i].name == catchParameters[j].name) { 184 throwDupIdError(catchParameters[j]); 185 } 186 } 187 188 for (let m = 0; m < bodyDecls.length; m++) { 189 if (bodyDecls[m] instanceof VarDecl) { 190 continue; 191 } 192 193 if (catchParameters[i].name == bodyDecls[m].name) { 194 throwDupIdError(bodyDecls[m]); 195 } 196 } 197 } 198} 199 200function getParameterNames(node: ts.FunctionLikeDeclaration, recorder: Recorder) { 201 let parameters = recorder.getParametersOfFunction(node); 202 let parameterNames: string[] = []; 203 204 if (!parameters) { 205 return; 206 } 207 208 parameters.forEach(funcParam => { 209 parameterNames.push(funcParam.name); 210 }); 211 212 return parameterNames; 213} 214 215function checkDuplicateParameter(node: ts.FunctionLikeDeclaration, recorder: Recorder) { 216 let parameters = recorder.getParametersOfFunction(node); 217 let tempNames: string[] = []; 218 if (!parameters) { 219 return; 220 } 221 parameters.forEach(param => { 222 // @ts-ignore 223 if (tempNames.includes(param.name)) { 224 throwDupIdError(param); 225 } else { 226 tempNames.push(param.name); 227 } 228 }); 229} 230 231function checkDuplicateParameterVar(parameterNames: string[] | undefined, scope: Scope) { 232 if (!parameterNames) { 233 return; 234 } 235 let decls = scope.getDecls(); 236 for (let i = 0; i < decls.length; i++) { 237 if ((decls[i] instanceof VarDecl) || (decls[i] instanceof FuncDecl)) { 238 continue; 239 } 240 let name = decls[i].name; 241 // @ts-ignore 242 if (parameterNames.includes(name)) { 243 throwDupIdError(decls[i]); 244 } 245 } 246} 247 248function checkDeclareGlobalId(decl: Decl, scope: Scope) { 249 if (!(scope instanceof GlobalScope)) { 250 return; 251 } 252 253 if ((decl instanceof VarDecl) || (decl instanceof CatchParameter)) { 254 return; 255 } 256 257 if (isGlobalIdentifier(decl.name) && isDeclInGlobal(<ts.Identifier>decl.node)) { 258 let sourceNode = jshelpers.getSourceFileOfNode(decl.node); 259 throw new DiagnosticError(decl.node, DiagnosticCode.Declaration_name_conflicts_with_built_in_global_identifier_0, sourceNode, [decl.name]) 260 } 261} 262 263function throwDupIdError(decl: Decl) { 264 let sourceNode = jshelpers.getSourceFileOfNode(decl.node); 265 if (decl.node.kind == ts.SyntaxKind.FunctionDeclaration) { 266 decl.node = <ts.Identifier>(<ts.FunctionDeclaration>decl.node).name; 267 } 268 throw new DiagnosticError(decl.node, DiagnosticCode.Duplicate_identifier_0, sourceNode, [decl.name]); 269} 270 271//**********************************Part 2: Implementing syntax check except declaration******************************************// 272export function checkSyntaxError(node: ts.Node, scope:Scope) { 273 checkSyntaxErrorForSloppyAndStrictMode(node); 274 if (isStrictMode(node) || CmdOptions.isModules()) { 275 checkSyntaxErrorForStrictMode(node, scope); 276 } 277} 278 279function checkBreakOrContinueStatement(node: ts.BreakOrContinueStatement) { 280 let curNode: ts.Node = node; 281 while (curNode) { 282 if (ts.isFunctionLike(curNode)) { 283 throw new DiagnosticError(node, DiagnosticCode.Jump_target_cannot_cross_function_boundary, jshelpers.getSourceFileOfNode(curNode)); 284 } 285 286 switch (curNode.kind) { 287 case ts.SyntaxKind.SwitchStatement: { 288 if (node.kind === ts.SyntaxKind.BreakStatement && !node.label) { 289 // unlabeled break within switch statement - ok 290 return; 291 } 292 break; 293 } 294 case ts.SyntaxKind.LabeledStatement: { 295 if (node.label && (<ts.LabeledStatement>curNode).label.escapedText === node.label.escapedText) { 296 // found matching label - verify that label usage is correct 297 // continue can only target labels that are on iteration statements 298 let isMisplacedContinueLabel = false; 299 if (node.kind === ts.SyntaxKind.ContinueStatement 300 && !jshelpers.isIterationStatement((<ts.LabeledStatement>curNode).statement, /*lookInLabeledStatement*/ true)) { 301 isMisplacedContinueLabel = true; 302 } 303 304 if (isMisplacedContinueLabel) { 305 throw new DiagnosticError(node, DiagnosticCode.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement, jshelpers.getSourceFileOfNode(curNode)); 306 } 307 308 return; 309 } 310 break; 311 } 312 default: { 313 if (jshelpers.isIterationStatement(curNode, /*lookInLabeledStatement*/ false) && !node.label) { 314 // unlabeled break or continue within iteration statement - ok 315 return false; 316 } 317 break; 318 } 319 } 320 321 curNode = curNode.parent; 322 } 323 324 let diagnosticCode; 325 326 if (node.label) { 327 if (node.kind == ts.SyntaxKind.BreakStatement) { 328 diagnosticCode = DiagnosticCode.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement; 329 } else { 330 diagnosticCode = DiagnosticCode.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement; 331 } 332 } else { 333 if (node.kind == ts.SyntaxKind.BreakStatement) { 334 diagnosticCode = DiagnosticCode.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement; 335 } else { 336 diagnosticCode = DiagnosticCode.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement; 337 } 338 } 339 340 throw new DiagnosticError(node, diagnosticCode, jshelpers.getSourceFileOfNode(node)); 341} 342 343function checkReturnStatement(node: ts.ReturnStatement) { 344 let func = jshelpers.getContainingFunction(node); 345 if (!func) { 346 let file = jshelpers.getSourceFileOfNode(node); 347 throw new DiagnosticError(node, DiagnosticCode.A_return_statement_can_only_be_used_within_a_function_body, file); 348 } 349} 350 351function checkMetaProperty(node: ts.MetaProperty) { 352 let text = jshelpers.getTextOfIdentifierOrLiteral(node.name); 353 let file = jshelpers.getSourceFileOfNode(node); 354 switch (node.keywordToken) { 355 case ts.SyntaxKind.NewKeyword: { 356 let args = [text, jshelpers.tokenToString(node.keywordToken), "target"]; 357 if (text != "target") { 358 throw new DiagnosticError(node, DiagnosticCode._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, file, args); 359 } 360 361 let func = getContainingFunctionDeclaration(node); 362 if (!func) { 363 throw new DiagnosticError(node, DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); 364 } else { 365 if (ts.isMethodDeclaration(func)) { 366 throw new DiagnosticError(node, DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); 367 } 368 if (ts.isArrowFunction(func) && !jshelpers.getNewTargetContainer(node)) { 369 throw new DiagnosticError(node, DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); 370 } 371 } 372 break; 373 } 374 case ts.SyntaxKind.ImportKeyword: { 375 if (text != "meta") { 376 let args = [text, jshelpers.tokenToString(node.keywordToken), "meta"]; 377 throw new DiagnosticError(node, DiagnosticCode._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, file, args); 378 } 379 break; 380 } 381 default: 382 break; 383 } 384} 385 386function checkNameInLetOrConstDeclarations(name: ts.Identifier | ts.BindingPattern) { 387 if (name.kind === ts.SyntaxKind.Identifier) { 388 if (name.originalKeywordKind === ts.SyntaxKind.LetKeyword) { 389 let file = jshelpers.getSourceFileOfNode(name); 390 throw new DiagnosticError(name, DiagnosticCode.The_let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations, file); 391 } 392 } else { 393 let elements = name.elements; 394 for (let element of elements) { 395 if (!ts.isOmittedExpression(element)) { 396 checkNameInLetOrConstDeclarations(element.name); 397 } 398 } 399 } 400} 401 402function checkDisallowedLetOrConstStatement(node: ts.VariableStatement) { 403 if (allowLetAndConstDeclarations(node.parent)) { 404 return; 405 } 406 407 if (jshelpers.isLet(node.declarationList)) { 408 throw new DiagnosticError(node, DiagnosticCode.The_let_declarations_can_only_be_declared_inside_a_block); 409 } 410 411 if (jshelpers.isVarConst(node.declarationList)) { 412 throw new DiagnosticError(node, DiagnosticCode.The_const_declarations_can_only_be_declared_inside_a_block); 413 } 414} 415 416function checkVariableDeclaration(node: ts.VariableDeclaration) { 417 let file = jshelpers.getSourceFileOfNode(node); 418 if (!ts.isForInStatement(node.parent.parent) && !ts.isForOfStatement(node.parent.parent) && !ts.isCatchClause(node.parent)) { 419 if (!node.initializer) { 420 if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) { 421 throw new DiagnosticError(node, DiagnosticCode.A_destructuring_declaration_must_have_an_initializer, file); 422 } 423 424 if (jshelpers.isVarConst(node)) { 425 throw new DiagnosticError(node, DiagnosticCode.The_const_declarations_must_be_initialized, file); 426 } 427 } 428 } 429 430 if (node.exclamationToken && (node.parent.parent.kind !== ts.SyntaxKind.VariableStatement || !node.type || node.initializer)) { 431 if (node.initializer) { 432 throw new DiagnosticError(node.exclamationToken, DiagnosticCode.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions, file); 433 } else { 434 throw new DiagnosticError(node.exclamationToken, DiagnosticCode.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations, file); 435 } 436 } 437 438 if (jshelpers.isLet(node) || jshelpers.isVarConst(node)) { 439 checkNameInLetOrConstDeclarations(node.name); 440 if (!isInBlockScope(node.parent.parent.parent) 441 && !ts.isForInStatement(node.parent.parent) 442 && !ts.isForOfStatement(node.parent.parent) 443 && !ts.isForStatement(node.parent.parent)) { 444 throw new DiagnosticError(node, DiagnosticCode.const_and_let_declarations_not_allowed_in_statement_positions, file); 445 } 446 } 447} 448 449function checkDecorators(node: ts.Node) { 450 if (!node.decorators) { 451 return; 452 } 453 454 let file = jshelpers.getSourceFileOfNode(node); 455 if (!jshelpers.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { 456 if (ts.isMethodDeclaration(node) && !jshelpers.nodeIsPresent((<ts.MethodDeclaration>node).body)) { 457 throw new DiagnosticError(node, DiagnosticCode.A_decorator_can_only_decorate_a_method_implementation_not_an_overload, file); 458 } else { 459 throw new DiagnosticError(node, DiagnosticCode.Decorators_are_not_valid_here, file); 460 } 461 } else if (ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node)) { 462 let accessors = jshelpers.getAllAccessorDeclarations((<ts.ClassDeclaration>node.parent).members, <ts.AccessorDeclaration>node); 463 if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) { 464 throw new DiagnosticError(node, DiagnosticCode.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name, file); 465 } 466 } 467} 468 469function checkAsyncModifier(node: ts.Node, asyncModifier: ts.Node) { 470 switch (node.kind) { 471 case ts.SyntaxKind.ArrowFunction: 472 case ts.SyntaxKind.FunctionDeclaration: 473 case ts.SyntaxKind.FunctionExpression: 474 case ts.SyntaxKind.MethodDeclaration: 475 return; 476 default: 477 break; 478 } 479 let file = jshelpers.getSourceFileOfNode(node); 480 throw new DiagnosticError(asyncModifier, DiagnosticCode._0_modifier_cannot_be_used_here, file, ["async"]) 481} 482 483function checkModifiers(node: ts.Node) { 484 if (!node.modifiers) { 485 return; 486 } 487 488 let lastStatic: ts.Node | undefined; 489 let lastDeclare: ts.Node | undefined; 490 let lastAsync: ts.Node | undefined; 491 let lastReadonly: ts.Node | undefined; 492 let flags = ts.ModifierFlags.None; 493 let file = jshelpers.getSourceFileOfNode(node); 494 495 for (let modifier of node.modifiers!) { 496 if (modifier.kind !== ts.SyntaxKind.ReadonlyKeyword) { 497 if (ts.isPropertySignature(node) || ts.isMethodSignature(node)) { 498 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_type_member, file, [jshelpers.tokenToString(modifier.kind)]); 499 } 500 if (ts.isIndexSignatureDeclaration(node)) { 501 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_an_index_signature, file, [jshelpers.tokenToString(modifier.kind)]); 502 } 503 } 504 switch (modifier.kind) { 505 case ts.SyntaxKind.ConstKeyword: { 506 if (ts.isEnumDeclaration(node)) { 507 throw new DiagnosticError(node, DiagnosticCode.A_class_member_cannot_have_the_0_keyword, file, [jshelpers.tokenToString(ts.SyntaxKind.ConstKeyword)]); 508 } 509 break; 510 } 511 case ts.SyntaxKind.PublicKeyword: 512 case ts.SyntaxKind.ProtectedKeyword: 513 case ts.SyntaxKind.PrivateKeyword: { 514 const text = visibilityToString(jshelpers.modifierToFlag(modifier.kind)); 515 516 if (flags & ts.ModifierFlags.AccessibilityModifier) { 517 throw new DiagnosticError(modifier, DiagnosticCode.Accessibility_modifier_already_seen, file); 518 } else if (flags & ts.ModifierFlags.Static) { 519 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "static"]); 520 } else if (flags & ts.ModifierFlags.Readonly) { 521 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "readonly"]); 522 } else if (flags & ts.ModifierFlags.Async) { 523 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "async"]); 524 } else if (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent)) { 525 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_or_namespace_element, file, [text]); 526 } else if (flags & ts.ModifierFlags.Abstract) { 527 if (modifier.kind === ts.SyntaxKind.PrivateKeyword) { 528 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, [text, "abstract"]); 529 } else { 530 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "abstract"]); 531 } 532 } else if (ts.isPropertyDeclaration(node) && ts.isPrivateIdentifier(node.name)) { 533 throw new DiagnosticError(modifier, DiagnosticCode.An_accessibility_modifier_cannot_be_used_with_a_private_identifier, file); 534 } 535 flags |= jshelpers.modifierToFlag(modifier.kind); 536 break; 537 } 538 case ts.SyntaxKind.StaticKeyword: { 539 if (flags & ts.ModifierFlags.Static) { 540 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["static"]); 541 } else if (flags & ts.ModifierFlags.Readonly) { 542 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["static", "readonly"]); 543 } else if (flags & ts.ModifierFlags.Async) { 544 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["static", "async"]); 545 } else if (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent)) { 546 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_or_namespace_element, file, ["static"]); 547 } else if (ts.isParameter(node)) { 548 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["static"]); 549 } else if (flags & ts.ModifierFlags.Abstract) { 550 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["static", "abstract"]); 551 } else if (ts.isPropertyDeclaration(node) && ts.isPrivateIdentifier(node.name)) { 552 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_a_private_identifier, file, ["static"]); 553 } 554 flags |= ts.ModifierFlags.Static; 555 lastStatic = modifier; 556 break; 557 } 558 case ts.SyntaxKind.ReadonlyKeyword: { 559 if (flags & ts.ModifierFlags.Readonly) { 560 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["readonly"]); 561 } else if (!ts.isPropertyDeclaration(node) && !ts.isPropertySignature(node) && !ts.isIndexSignatureDeclaration(node) && !ts.isParameter(node)) { 562 // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. 563 throw new DiagnosticError(modifier, DiagnosticCode.The_readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature, file); 564 } 565 flags |= ts.ModifierFlags.Readonly; 566 lastReadonly = modifier; 567 break; 568 } 569 case ts.SyntaxKind.ExportKeyword: { 570 if (flags & ts.ModifierFlags.Export) { 571 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["export"]); 572 } else if (flags & ts.ModifierFlags.Ambient) { 573 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "declare"]); 574 } else if (flags & ts.ModifierFlags.Abstract) { 575 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "abstract"]); 576 } else if (flags & ts.ModifierFlags.Async) { 577 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "async"]); 578 } else if (ts.isClassLike(node.parent)) { 579 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_class_elements_of_this_kind, file, ["export"]); 580 } else if (ts.isParameter(node)) { 581 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["export"]); 582 } 583 flags |= ts.ModifierFlags.Export; 584 break; 585 } 586 case ts.SyntaxKind.DefaultKeyword: { 587 let container = ts.isSourceFile(node.parent) ? node.parent : node.parent.parent; 588 if (ts.isModuleDeclaration(container) && !jshelpers.isAmbientModule(container)) { 589 throw new DiagnosticError(modifier, DiagnosticCode.A_default_export_can_only_be_used_in_an_ECMAScript_style_module, file); 590 } 591 592 flags |= ts.ModifierFlags.Default; 593 break; 594 } 595 case ts.SyntaxKind.DeclareKeyword: { 596 if (flags & ts.ModifierFlags.Ambient) { 597 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["declare"]); 598 } else if (flags & ts.ModifierFlags.Async) { 599 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_in_an_ambient_context, file, ["async"]); 600 } else if (ts.isClassLike(node.parent) && !ts.isPropertyDeclaration(node)) { 601 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_class_elements_of_this_kind, file, ["declare"]); 602 } else if (ts.isParameter(node)) { 603 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["declare"]); 604 } else if (ts.isPropertyDeclaration(node) && ts.isPrivateIdentifier(node.name)) { 605 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_a_private_identifier, file, ["declare"]); 606 } 607 flags |= ts.ModifierFlags.Ambient; 608 lastDeclare = modifier; 609 break; 610 } 611 case ts.SyntaxKind.AbstractKeyword: { 612 if (flags & ts.ModifierFlags.Abstract) { 613 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["abstract"]); 614 } 615 if (ts.isClassDeclaration(node) && ts.isConstructorTypeNode(node)) { 616 if (!ts.isMethodDeclaration(node) && !ts.isPropertyDeclaration(node) && !ts.isGetAccessorDeclaration(node) && !ts.isSetAccessorDeclaration(node)) { 617 throw new DiagnosticError(modifier, DiagnosticCode.The_abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration, file); 618 } 619 if (flags & ts.ModifierFlags.Static) { 620 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["static", "abstract"]); 621 } 622 if (flags & ts.ModifierFlags.Private) { 623 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["private", "abstract"]); 624 } 625 if (flags & ts.ModifierFlags.Async && lastAsync) { 626 throw new DiagnosticError(lastAsync, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["async", "abstract"]); 627 } 628 } 629 let name = (<ts.NamedDeclaration>node).name; 630 if (name && ts.isPrivateIdentifier(name)) { 631 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_a_private_identifier, file, ["abstract"]); 632 } 633 634 flags |= ts.ModifierFlags.Abstract; 635 break; 636 } 637 case ts.SyntaxKind.AsyncKeyword: { 638 if (flags & ts.ModifierFlags.Async) { 639 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["async"]); 640 } else if (flags & ts.ModifierFlags.Ambient) { 641 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_in_an_ambient_context, file, ["async"]); 642 } else if (ts.isParameter(node)) { 643 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["async"]); 644 } 645 if (flags & ts.ModifierFlags.Abstract) { 646 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["async", "abstract"]); 647 } 648 flags |= ts.ModifierFlags.Async; 649 lastAsync = modifier; 650 break; 651 } 652 default: 653 break; 654 } 655 } 656 657 if (ts.isConstructorDeclaration(node)) { 658 if (flags & ts.ModifierFlags.Static) { 659 throw new DiagnosticError(lastStatic!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["static"]); 660 } 661 if (flags & ts.ModifierFlags.Abstract) { 662 throw new DiagnosticError(lastStatic!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["abstract"]); 663 } else if (flags & ts.ModifierFlags.Async) { 664 throw new DiagnosticError(lastAsync!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["async"]); 665 } else if (flags & ts.ModifierFlags.Readonly) { 666 throw new DiagnosticError(lastReadonly!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["readonly"]); 667 } 668 } else if ((ts.isImportDeclaration(node) || ts.isImportEqualsDeclaration(node)) && flags & ts.ModifierFlags.Ambient) { 669 throw new DiagnosticError(lastDeclare!, DiagnosticCode.A_0_modifier_cannot_be_used_with_an_import_declaration, file, ["declare"]); 670 } else if (ts.isParameter(node) && (flags & ts.ModifierFlags.ParameterPropertyModifier) && isBindingPattern((<ts.ParameterDeclaration>node).name)) { 671 throw new DiagnosticError(node, DiagnosticCode.A_parameter_property_may_not_be_declared_using_a_binding_pattern, file); 672 } else if (ts.isParameter(node) && (flags & ts.ModifierFlags.ParameterPropertyModifier) && (<ts.ParameterDeclaration>node).dotDotDotToken) { 673 throw new DiagnosticError(node, DiagnosticCode.A_parameter_property_cannot_be_declared_using_a_rest_parameter, file); 674 } 675 676 if (flags & ts.ModifierFlags.Async) { 677 checkAsyncModifier(node, lastAsync!); 678 } 679} 680 681function checkVariableDeclarationList(declarationList: ts.VariableDeclarationList) { 682 let declarations = declarationList.declarations; 683 if (!declarations.length) { 684 throw new DiagnosticError(declarationList, DiagnosticCode.Identifier_expected); 685 } 686 687 let decl = declarations[0].name; 688 if (isBindingPattern(decl)) { 689 checkBindingPattern(<ts.BindingPattern>decl); 690 } 691} 692 693function checkVariableStatement(node: ts.VariableStatement) { 694 checkDecorators(node); 695 checkModifiers(node); 696 checkVariableDeclarationList(node.declarationList); 697 checkDisallowedLetOrConstStatement(node); 698} 699 700function checkForInOrForOfStatement(stmt: ts.ForInOrOfStatement) { 701 let file = jshelpers.getSourceFileOfNode(stmt); 702 let leftExpr = stmt.initializer; 703 if (ts.isParenthesizedExpression(leftExpr)) { 704 leftExpr = findInnerExprOfParenthesis(leftExpr); 705 } 706 if (ts.isVariableDeclarationList(leftExpr)) { 707 let variableList = <ts.VariableDeclarationList>leftExpr; 708 checkVariableDeclarationList(variableList); 709 let declarations = variableList.declarations; 710 711 if (declarations.length > 1) { 712 if (ts.isForInStatement(stmt)) { 713 throw new DiagnosticError(variableList.declarations[1], DiagnosticCode.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement, file); 714 } else { 715 throw new DiagnosticError(variableList.declarations[1], DiagnosticCode.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement, file); 716 } 717 } 718 719 if (declarations[0].initializer) { 720 if (ts.isForInStatement(stmt)) { 721 throw new DiagnosticError(declarations[0].name, DiagnosticCode.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer, file); 722 } else { 723 throw new DiagnosticError(declarations[0].name, DiagnosticCode.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer, file); 724 } 725 } 726 727 if (declarations[0].type) { 728 if (ts.isForInStatement(stmt)) { 729 throw new DiagnosticError(declarations[0], DiagnosticCode.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation, file); 730 } else { 731 throw new DiagnosticError(declarations[0], DiagnosticCode.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation, file); 732 } 733 } 734 } else { 735 isInVaildAssignmentLeftSide(<ts.Expression>leftExpr); 736 737 if (ts.isArrayLiteralExpression(leftExpr) || ts.isObjectLiteralExpression(leftExpr)) { 738 checkDestructuringAssignmentLhs(leftExpr); 739 } 740 } 741} 742 743function checkForInOrForOfVariableDeclaration(iterationStatement: ts.ForInOrOfStatement) { 744 let variableDeclarationList = <ts.VariableDeclarationList>iterationStatement.initializer; 745 // checkGrammarForInOrForOfStatement will check that there is exactly one declaration. 746 if (variableDeclarationList.declarations.length >= 1) { 747 checkVariableDeclaration(variableDeclarationList.declarations[0]); 748 } 749} 750 751function checkForInStatement(node: ts.ForInStatement) { 752 checkForInOrForOfStatement(node); 753 754 let file = jshelpers.getSourceFileOfNode(node); 755 // for (let VarDecl in Expr) Statement 756 if (ts.isVariableDeclarationList(node.initializer)) { 757 checkForInOrForOfVariableDeclaration(node); 758 } else { 759 let varExpr = node.initializer; 760 if (ts.isArrayLiteralExpression(varExpr) || ts.isObjectLiteralExpression(varExpr)) { 761 throw new DiagnosticError(varExpr, DiagnosticCode.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern, file); 762 } 763 } 764} 765 766const enum OuterExpressionKinds { 767 Parentheses = 1 << 0, 768 TypeAssertions = 1 << 1, 769 NonNullAssertions = 1 << 2, 770 PartiallyEmittedExpressions = 1 << 3, 771 Assertions = TypeAssertions | NonNullAssertions, 772 All = Parentheses | Assertions | PartiallyEmittedExpressions 773} 774 775function checkReferenceExpression(expr: ts.Expression, invalidReferenceCode: DiagnosticCode, invalidOptionalChainCode: DiagnosticCode) { 776 let node = jshelpers.skipOuterExpressions(expr, OuterExpressionKinds.Assertions | OuterExpressionKinds.Parentheses); 777 if (node.kind !== ts.SyntaxKind.Identifier && node.kind !== ts.SyntaxKind.PropertyAccessExpression && node.kind !== ts.SyntaxKind.ElementAccessExpression) { 778 throw new DiagnosticError(expr, invalidReferenceCode); 779 } 780 781 if (node.flags & ts.NodeFlags.OptionalChain) { 782 throw new DiagnosticError(expr, invalidOptionalChainCode); 783 } 784} 785 786function checkReferenceAssignment(node: ts.Expression) { 787 let invalidReferenceCode: DiagnosticCode; 788 let invalidOptionalChainCode: DiagnosticCode; 789 790 if (ts.isSpreadAssignment(node.parent)) { 791 invalidReferenceCode = DiagnosticCode.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access; 792 invalidOptionalChainCode = DiagnosticCode.The_target_of_an_object_rest_assignment_may_not_be_an_optional_property_access; 793 } else { 794 invalidReferenceCode = DiagnosticCode.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; 795 invalidOptionalChainCode = DiagnosticCode.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access; 796 } 797 798 checkReferenceExpression(node, invalidReferenceCode, invalidOptionalChainCode); 799} 800 801function checkDestructuringAssignment(node: ts.Expression | ts.ShorthandPropertyAssignment) { 802 let target: ts.Expression; 803 if (ts.isShorthandPropertyAssignment(node)) { 804 let prop = <ts.ShorthandPropertyAssignment>node; 805 target = prop.name; 806 } else { 807 target = node; 808 } 809 810 if (ts.isBinaryExpression(target) && (<ts.BinaryExpression>target).operatorToken.kind === ts.SyntaxKind.EqualsToken) { 811 checkBinaryExpression(<ts.BinaryExpression>target); 812 target = (<ts.BinaryExpression>target).left; 813 } 814 815 if (ts.isObjectLiteralExpression(target)) { 816 checkObjectLiteralExpression(target); 817 } 818 819 checkReferenceAssignment(target); 820 821} 822 823function checkForOfStatement(node: ts.ForOfStatement) { 824 checkForInOrForOfStatement(node); 825 826 if (ts.isVariableDeclarationList(node.initializer)) { 827 checkForInOrForOfVariableDeclaration(node); 828 } else { 829 let varExpr = node.initializer; 830 831 if (ts.isArrayLiteralExpression(varExpr) || ts.isObjectLiteralExpression(varExpr)) { 832 checkDestructuringAssignment(varExpr); 833 } else { 834 checkReferenceExpression( 835 varExpr, 836 DiagnosticCode.The_left_hand_side_of_a_for_of_statement_must_be_a_variable_or_a_property_access, 837 DiagnosticCode.The_left_hand_side_of_a_for_of_statement_may_not_be_an_optional_property_access); 838 } 839 } 840} 841 842function checkClassDeclaration(node: ts.ClassLikeDeclaration) { 843 checkClassDeclarationHeritageClauses(node); 844 let hasConstructorImplementation = false; 845 let file = jshelpers.getSourceFileOfNode(node); 846 node.members.forEach(member => { 847 switch (member.kind) { 848 case ts.SyntaxKind.Constructor: { 849 if (hasConstructorImplementation) { 850 throw new DiagnosticError(node, DiagnosticCode.Multiple_constructor_implementations_are_not_allowed, file); 851 } else { 852 hasConstructorImplementation = true; 853 } 854 break; 855 } 856 case ts.SyntaxKind.MethodDeclaration: 857 case ts.SyntaxKind.SetAccessor: 858 checkFunctionLikeDeclaration(<ts.FunctionLikeDeclaration | ts.MethodSignature>member); 859 break; 860 case ts.SyntaxKind.GetAccessor: 861 checkGetAccessor(<ts.GetAccessorDeclaration>member); 862 break; 863 default: 864 break; 865 } 866 }); 867 868 // Class declaration not allowed in statement position 869 if (isStatement(node.parent.kind)) { 870 throw new DiagnosticError(node, DiagnosticCode.Class_declaration_not_allowed_in_statement_position, file); 871 } 872 873} 874 875function checkClassDeclarationHeritageClauses(node: ts.ClassLikeDeclaration) { 876 let hasExtendsKeyWords = false; 877 checkDecorators(node); 878 checkModifiers(node); 879 if (node.heritageClauses == undefined) { 880 return; 881 } 882 883 let file = jshelpers.getSourceFileOfNode(node); 884 for (let heritageClause of node.heritageClauses) { 885 if (heritageClause.token == ts.SyntaxKind.ExtendsKeyword) { 886 if (hasExtendsKeyWords) { 887 throw new DiagnosticError(heritageClause, DiagnosticCode.The_extends_clause_already_seen, file); 888 } 889 890 if (heritageClause.types.length > 1) { 891 throw new DiagnosticError(heritageClause, DiagnosticCode.Classes_can_only_extend_a_single_class); 892 } 893 hasExtendsKeyWords = true; 894 } 895 } 896} 897 898function checkBinaryExpression(node: ts.BinaryExpression) { 899 // AssignmentExpression 900 if (isAssignmentOperator(node.operatorToken.kind)) { 901 let leftExpr: ts.Expression = node.left; 902 if (ts.isParenthesizedExpression(leftExpr)) { 903 leftExpr = findInnerExprOfParenthesis(leftExpr); 904 } 905 906 if (node.operatorToken.kind == ts.SyntaxKind.EqualsToken) { 907 if (ts.isArrayLiteralExpression(leftExpr) || ts.isObjectLiteralExpression(leftExpr)) { 908 checkDestructuringAssignmentLhs(leftExpr); 909 } 910 } 911 912 isInVaildAssignmentLeftSide(leftExpr); 913 } 914} 915 916function isInVaildAssignmentLeftSide(leftExpr: ts.Expression) { 917 if (jshelpers.isKeyword(leftExpr.kind) 918 || leftExpr.kind == ts.SyntaxKind.NumericLiteral 919 || leftExpr.kind == ts.SyntaxKind.StringLiteral) { 920 throw new DiagnosticError(leftExpr, DiagnosticCode.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access); 921 } 922} 923 924 925function checkContextualIdentifier(node: ts.Identifier) { 926 if (jshelpers.isIdentifierName(node)) { 927 return; 928 } 929 930 let file = jshelpers.getSourceFileOfNode(node); 931 if (node.originalKeywordKind === ts.SyntaxKind.AwaitKeyword) { 932 if (jshelpers.isExternalOrCommonJsModule(file) && jshelpers.isInTopLevelContext(node)) { 933 throw new DiagnosticError(node, DiagnosticCode.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, file, jshelpers.declarationNameToString(node)); 934 } else if (node.flags & ts.NodeFlags.AwaitContext) { 935 throw new DiagnosticError(node, DiagnosticCode.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, file, jshelpers.declarationNameToString(node)); 936 } 937 } else if (node.originalKeywordKind === ts.SyntaxKind.YieldKeyword && node.flags & ts.NodeFlags.YieldContext) { 938 throw new DiagnosticError(node, DiagnosticCode.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, file, jshelpers.declarationNameToString(node)); 939 } 940} 941 942function checkComputedPropertyName(node: ts.Node) { 943 if (!ts.isComputedPropertyName(node)) { 944 return; 945 } 946 947 let expression = node.expression; 948 if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.CommaToken) { 949 let file = jshelpers.getSourceFileOfNode(node); 950 throw new DiagnosticError(expression, DiagnosticCode.A_comma_expression_is_not_allowed_in_a_computed_property_name, file); 951 } 952} 953 954const enum DeclarationMeaning { 955 GetAccessor = 1, 956 SetAccessor = 2, 957 PropertyAssignment = 4, 958 Method = 8, 959 GetOrSetAccessor = GetAccessor | SetAccessor, 960 PropertyAssignmentOrMethod = PropertyAssignment | Method, 961} 962 963function checkObjectLiteralExpression(node: ts.ObjectLiteralExpression) { 964 let inDestructuring = jshelpers.isAssignmentTarget(node); 965 let file = jshelpers.getSourceFileOfNode(node); 966 let seen = new Map<ts.__String, DeclarationMeaning>(); 967 968 for (let prop of node.properties) { 969 if (ts.isSpreadAssignment(prop)) { 970 if (inDestructuring) { 971 let expression = jshelpers.skipParentheses(prop.expression); 972 if (ts.isArrayLiteralExpression(expression) || ts.isObjectLiteralExpression(expression)) { 973 throw new DiagnosticError(prop.expression, DiagnosticCode.A_rest_element_cannot_contain_a_binding_pattern, file); 974 } 975 } 976 continue; 977 } 978 let name = prop.name; 979 if (ts.isComputedPropertyName(name)) { 980 checkComputedPropertyName(name); 981 } 982 983 if (ts.isShorthandPropertyAssignment(prop) && !inDestructuring && prop.objectAssignmentInitializer) { 984 throw new DiagnosticError(prop.equalsToken!, DiagnosticCode.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern, file); 985 } 986 987 if (ts.isPrivateIdentifier(name)) { 988 throw new DiagnosticError(name, DiagnosticCode.Private_identifiers_are_not_allowed_outside_class_bodies, file); 989 } 990 991 if (prop.modifiers) { 992 for (let mod of prop.modifiers) { 993 if (!ts.isMethodDeclaration(prop) || mod.kind != ts.SyntaxKind.AsyncKeyword) { 994 throw new DiagnosticError(mod, DiagnosticCode._0_modifier_cannot_be_used_here, file, [jshelpers.getTextOfNode(mod)]); 995 } 996 } 997 } 998 999 /** 1000 * It is a Syntax Error if PropertyNameList of PropertyDefinitionList contains any duplicate entries for "__proto__" and 1001 * at least two of those entries were obtained from productions of the form 1002 * PropertyDefinition : PropertyName : AssignmentExpression . 1003 */ 1004 let curKind = getPropertieDeclaration(prop, name); 1005 if (!curKind) continue; 1006 if (!inDestructuring) { 1007 let effectName = jshelpers.getPropertyNameForPropertyNameNode(name); 1008 if (!effectName || ts.isComputedPropertyName(name)) continue; 1009 let existKind = seen.get(effectName); 1010 if (!existKind) { 1011 seen.set(effectName, curKind); 1012 } else { 1013 if ((curKind & DeclarationMeaning.PropertyAssignmentOrMethod) && (existKind & DeclarationMeaning.PropertyAssignmentOrMethod)) { 1014 if (effectName === "___proto__") { 1015 throw new DiagnosticError(name, DiagnosticCode.Duplicate_identifier_0, file, [jshelpers.getTextOfNode(name)]); 1016 } 1017 } 1018 } 1019 } 1020 } 1021} 1022 1023function checkInvalidExclamationToken(exclamationToken: ts.ExclamationToken | undefined) { 1024 if (!!exclamationToken) { 1025 let file = jshelpers.getSourceFileOfNode(exclamationToken); 1026 throw new DiagnosticError(exclamationToken, DiagnosticCode.A_definite_assignment_assertion_is_not_permitted_in_this_context, file); 1027 } 1028} 1029 1030function checkInvalidQuestionMark(questionToken: ts.QuestionToken | undefined) { 1031 if (!!questionToken) { 1032 let file = jshelpers.getSourceFileOfNode(questionToken); 1033 throw new DiagnosticError(questionToken, DiagnosticCode.An_object_member_cannot_be_declared_optional, file); 1034 } 1035} 1036 1037// @ts-ignore 1038function getPropertieDeclaration(node: ts.Node, name: ts.Node) { 1039 let decl = undefined; 1040 if (ts.isShorthandPropertyAssignment(node)) { 1041 checkInvalidExclamationToken(node.exclamationToken); 1042 } else if (ts.isPropertyAssignment(node)) { 1043 checkInvalidQuestionMark(node.questionToken); 1044 decl = DeclarationMeaning.PropertyAssignment; 1045 } else if (ts.isMethodDeclaration(node)) { 1046 decl = DeclarationMeaning.Method; 1047 } else if (ts.isGetAccessor(node)) { 1048 checkGetAccessor(node); 1049 decl = DeclarationMeaning.GetAccessor; 1050 } else if (ts.isSetAccessor(node)) { 1051 decl = DeclarationMeaning.SetAccessor; 1052 } else { 1053 LOGE("Unexpected syntax kind:" + node.kind); 1054 } 1055 return decl; 1056} 1057 1058function checkDisallowedTrailingComma(list: ts.NodeArray<ts.Node> | undefined) { 1059 if (list && list.hasTrailingComma) { 1060 let file = jshelpers.getSourceFileOfNode(list[0]); 1061 throw new DiagnosticError(list[0], DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, file); 1062 } 1063} 1064 1065function checkParameters(parameters: ts.NodeArray<ts.ParameterDeclaration>) { 1066 let count = parameters.length; 1067 let optionalParameter = false; 1068 1069 for (let i = 0; i < count; i++) { 1070 let parameter = parameters[i]; 1071 let file = jshelpers.getSourceFileOfNode(parameter); 1072 if (parameter.dotDotDotToken) { 1073 if (i != count - 1) { 1074 throw new DiagnosticError(parameter.dotDotDotToken, DiagnosticCode.A_rest_parameter_must_be_last_in_a_parameter_list, file); 1075 } 1076 1077 checkDisallowedTrailingComma(parameters); 1078 1079 if (parameter.initializer) { 1080 throw new DiagnosticError(parameter.name, DiagnosticCode.A_rest_parameter_cannot_have_an_initializer, file); 1081 } 1082 1083 if (parameter.questionToken) { 1084 throw new DiagnosticError(parameter.questionToken, DiagnosticCode.A_rest_parameter_cannot_be_optional, file); 1085 } 1086 1087 } else if (isOptionalParameter(parameter)) { 1088 optionalParameter = true; 1089 if (parameter.questionToken && parameter.initializer) { 1090 throw new DiagnosticError(parameter.name, DiagnosticCode.Parameter_cannot_have_question_mark_and_initializer, file); 1091 } 1092 } 1093 else if (optionalParameter && !parameter.initializer) { 1094 throw new DiagnosticError(parameter.name, DiagnosticCode.A_required_parameter_cannot_follow_an_optional_parameter, file); 1095 } 1096 } 1097} 1098 1099function checkArrowFunction(node: ts.Node) { 1100 if (!ts.isArrowFunction(node)) { 1101 return; 1102 } 1103 1104 const { equalsGreaterThanToken } = node; 1105 let file = jshelpers.getSourceFileOfNode(node); 1106 const startLine = file.getLineAndCharacterOfPosition(equalsGreaterThanToken.pos).line; 1107 const endLine = file.getLineAndCharacterOfPosition(equalsGreaterThanToken.end).line; 1108 if (startLine !== endLine) { 1109 throw new DiagnosticError(equalsGreaterThanToken, DiagnosticCode.Line_terminator_not_permitted_before_arrow, file); 1110 } 1111} 1112 1113function checkFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration | ts.MethodSignature) { 1114 checkDecorators(node); 1115 checkModifiers(node); 1116 checkParameters(node.parameters); 1117 checkArrowFunction(node); 1118} 1119 1120function checkLabeledStatement(node: ts.LabeledStatement) { 1121 let file = jshelpers.getSourceFileOfNode(node); 1122 jshelpers.findAncestor(node.parent, current => { 1123 if (jshelpers.isFunctionLike(current)) { 1124 return "quit"; 1125 } 1126 1127 if (ts.isLabeledStatement(current) && (<ts.LabeledStatement>current).label.escapedText === node.label.escapedText) { 1128 throw new DiagnosticError(node.label, DiagnosticCode.Duplicate_label_0, file, [jshelpers.getTextOfNode(node.label)]); 1129 } 1130 return false; 1131 }); 1132 1133 let statement = node.statement; 1134 if (ts.isVariableStatement(statement)) { 1135 let variableStatement = <ts.VariableStatement>statement; 1136 if (jshelpers.isLet(variableStatement.declarationList)) { 1137 throw new DiagnosticError(node, DiagnosticCode.Lexical_declaration_let_not_allowed_in_statement_position); 1138 } 1139 1140 if (jshelpers.isVarConst(variableStatement.declarationList)) { 1141 throw new DiagnosticError(node, DiagnosticCode.Lexical_declaration_const_not_allowed_in_statement_position); 1142 } 1143 } 1144} 1145 1146function checkGetAccessor(node: ts.GetAccessorDeclaration) { 1147 checkFunctionLikeDeclaration(node); 1148 if (node.parameters.length != 0) { 1149 throw new DiagnosticError(node, DiagnosticCode.Getter_must_not_have_any_formal_parameters); 1150 } 1151} 1152 1153function isValidUseSuperExpression(node: ts.Node, isCallExpression: boolean): boolean { 1154 if (!node) { 1155 return false; 1156 } 1157 1158 if (isCallExpression) { 1159 return ts.isConstructorDeclaration(node); 1160 } 1161 1162 if (!ts.isClassLike(node.parent) && !ts.isObjectLiteralExpression(node.parent)) { 1163 return false; 1164 } 1165 1166 return ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node) || 1167 ts.isPropertyDeclaration(node) || ts.isPropertySignature(node) || ts.isConstructorDeclaration(node); 1168} 1169 1170function checkSuperExpression(node: ts.SuperExpression) { 1171 let file = jshelpers.getSourceFileOfNode(node); 1172 let isCallExpression = false; 1173 if (ts.isCallExpression(node.parent) && (<ts.CallExpression>node.parent).expression === node) { 1174 isCallExpression = true; 1175 } 1176 1177 let container = jshelpers.getSuperContainer(node, true); 1178 1179 if (!isCallExpression) { 1180 while (container && ts.isArrowFunction(container)) { 1181 container = jshelpers.getSuperContainer(container, true); 1182 } 1183 } 1184 1185 let isSuperExpCanUse = isValidUseSuperExpression(container, isCallExpression); 1186 1187 if (!isSuperExpCanUse) { 1188 let current = jshelpers.findAncestor(node, n => n === container ? "quit" : ts.isComputedPropertyName(n)); 1189 if (current && ts.isComputedPropertyName(current)) { 1190 throw new DiagnosticError(node, DiagnosticCode.The_super_cannot_be_referenced_in_a_computed_property_name, file); 1191 } 1192 let containerFunc = jshelpers.findAncestor(node, ts.isConstructorDeclaration); 1193 if (containerFunc) { 1194 return; 1195 } 1196 if (isCallExpression) { 1197 throw new DiagnosticError(node, DiagnosticCode.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors, file); 1198 } 1199 1200 if (!container || !container.parent || !ts.isClassLike(container.parent) || ts.isObjectLiteralExpression(container.parent)) { 1201 throw new DiagnosticError(node, DiagnosticCode.The_super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions, file); 1202 } 1203 1204 throw new DiagnosticError(node, DiagnosticCode.The_super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class, file); 1205 } 1206} 1207 1208function checkImportExpression(node: ts.ImportExpression) { 1209 let args = (<ts.CallExpression>node.parent).arguments; 1210 if (args.length != 1) { 1211 throw new DiagnosticError(node, DiagnosticCode.Dynamic_imports_can_only_accept_a_module_specifier_optional_assertion_is_not_supported_yet); 1212 } 1213 1214 args.forEach(arg => { 1215 if (ts.isSpreadElement(arg)) { 1216 throw new DiagnosticError(node, DiagnosticCode.Argument_of_dynamic_import_cannot_be_spread_element); 1217 } 1218 }); 1219} 1220 1221function checkRegularExpression(regexp: ts.RegularExpressionLiteral) { 1222 let regexpText = regexp.text; 1223 let regexpParse = require("regexpp").RegExpParser; 1224 new regexpParse().parseLiteral(regexpText); 1225} 1226 1227function checkThrowStatement(node: ts.ThrowStatement) { 1228 if (ts.isIdentifier(node.expression) && (<ts.Identifier>node.expression).text === '') { 1229 throw new DiagnosticError(node, DiagnosticCode.Line_break_not_permitted_here, jshelpers.getSourceFileOfNode(node)); 1230 } 1231} 1232 1233function checkSyntaxErrorForSloppyAndStrictMode(node: ts.Node) { 1234 switch (node.kind) { 1235 case ts.SyntaxKind.BreakStatement: 1236 case ts.SyntaxKind.ContinueStatement: 1237 checkBreakOrContinueStatement(<ts.BreakOrContinueStatement>node); 1238 break; 1239 case ts.SyntaxKind.ReturnStatement: 1240 checkReturnStatement(<ts.ReturnStatement>node); 1241 break; 1242 case ts.SyntaxKind.ComputedPropertyName: 1243 checkComputedPropertyName(<ts.ComputedPropertyName>node); 1244 break; 1245 case ts.SyntaxKind.ObjectBindingPattern: 1246 case ts.SyntaxKind.ArrayBindingPattern: 1247 checkBindingPattern(<ts.BindingPattern>node); 1248 break; 1249 case ts.SyntaxKind.MetaProperty: 1250 checkMetaProperty(<ts.MetaProperty>node); 1251 break; 1252 case ts.SyntaxKind.VariableDeclaration: 1253 checkVariableDeclaration(<ts.VariableDeclaration>node); 1254 break; 1255 case ts.SyntaxKind.VariableStatement: 1256 checkVariableStatement(<ts.VariableStatement>node); 1257 break; 1258 case ts.SyntaxKind.ForInStatement: 1259 checkForInStatement(<ts.ForInStatement>node); 1260 break; 1261 case ts.SyntaxKind.ForOfStatement: 1262 checkForOfStatement(<ts.ForOfStatement>node); 1263 break; 1264 case ts.SyntaxKind.ClassDeclaration: 1265 case ts.SyntaxKind.ClassExpression: 1266 checkClassDeclaration(<ts.ClassLikeDeclaration>node); 1267 break; 1268 case ts.SyntaxKind.SuperKeyword: 1269 checkSuperExpression(<ts.SuperExpression>node); 1270 break; 1271 case ts.SyntaxKind.ImportKeyword: 1272 checkImportExpression(<ts.ImportExpression>node); 1273 break; 1274 case ts.SyntaxKind.BinaryExpression: 1275 checkBinaryExpression(<ts.BinaryExpression>node); 1276 break; 1277 case ts.SyntaxKind.Identifier: 1278 checkContextualIdentifier(<ts.Identifier>node); 1279 break; 1280 case ts.SyntaxKind.ObjectLiteralExpression: 1281 checkObjectLiteralExpression(<ts.ObjectLiteralExpression>node); 1282 break; 1283 case ts.SyntaxKind.FunctionDeclaration: 1284 case ts.SyntaxKind.MethodSignature: 1285 case ts.SyntaxKind.MethodDeclaration: 1286 case ts.SyntaxKind.SetAccessor: 1287 case ts.SyntaxKind.Constructor: 1288 case ts.SyntaxKind.FunctionExpression: 1289 case ts.SyntaxKind.ArrowFunction: 1290 checkFunctionLikeDeclaration(<ts.FunctionLikeDeclaration | ts.MethodSignature>node); 1291 break; 1292 case ts.SyntaxKind.GetAccessor: 1293 checkGetAccessor(<ts.GetAccessorDeclaration>node); 1294 break; 1295 case ts.SyntaxKind.LabeledStatement: 1296 checkLabeledStatement(<ts.LabeledStatement>node); 1297 break; 1298 case ts.SyntaxKind.RegularExpressionLiteral: 1299 checkRegularExpression(<ts.RegularExpressionLiteral>node); 1300 break; 1301 case ts.SyntaxKind.ThrowStatement: 1302 checkThrowStatement(<ts.ThrowStatement>node); 1303 break; 1304 default: 1305 break; 1306 } 1307} 1308 1309function checkDestructuringAssignmentLhs(lhs: ts.Expression) { 1310 let file = getSourceFileOfNode(lhs); 1311 if (ts.isArrayLiteralExpression(lhs)) { 1312 let elements = lhs.elements; 1313 1314 for (let i = 0; i < elements.length; i++) { 1315 let target = elements[i]; 1316 1317 if (ts.isSpreadElement(target)) { 1318 if (i != elements.length - 1) { 1319 throw new DiagnosticError(target, DiagnosticCode.A_rest_element_must_be_last_in_a_destructuring_pattern, file); 1320 } 1321 1322 if (elements.hasTrailingComma) { 1323 throw new DiagnosticError(target, DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, file); 1324 } 1325 1326 if (ts.isArrayLiteralExpression(target.expression) || ts.isObjectLiteralExpression(target.expression)) { 1327 checkDestructuringAssignmentLhs(target.expression); 1328 } 1329 1330 continue; 1331 } 1332 1333 target = ts.isBinaryExpression(target) ? target.left : target; 1334 1335 if (ts.isOmittedExpression(target) || ts.isElementAccessExpression(target)) { 1336 continue; 1337 } 1338 1339 if (ts.isIdentifier(target)) { 1340 let name = jshelpers.getTextOfIdentifierOrLiteral(target); 1341 1342 if (name == MandatoryArguments || name == "eval") { 1343 throw new DiagnosticError(target, DiagnosticCode.Property_destructuring_pattern_expected, file); 1344 } 1345 continue; 1346 } 1347 1348 if (ts.isPropertyAccessExpression(target)) { 1349 if (target.questionDotToken) { 1350 throw new DiagnosticError(target, DiagnosticCode.Property_destructuring_pattern_expected, file); 1351 } 1352 1353 continue; 1354 } 1355 1356 if (ts.isArrayLiteralExpression(target) || ts.isObjectLiteralExpression(target)) { 1357 checkDestructuringAssignmentLhs(target); 1358 continue; 1359 } 1360 1361 throw new DiagnosticError(target, DiagnosticCode.Property_destructuring_pattern_expected, file); 1362 } 1363 } 1364 1365 if (ts.isObjectLiteralExpression(lhs)) { 1366 let elements = lhs.properties; 1367 1368 for (let i = 0; i < elements.length; i++) { 1369 let element = elements[i]; 1370 1371 if (ts.isSpreadAssignment(element)) { 1372 if (i != elements.length - 1) { 1373 let file = getSourceFileOfNode(lhs); 1374 throw new DiagnosticError(element, DiagnosticCode.A_rest_element_must_be_last_in_a_destructuring_pattern, file); 1375 } 1376 continue; 1377 } 1378 1379 if (ts.isPropertyAssignment(element)) { 1380 let target = ts.isBinaryExpression(element.initializer) ? element.initializer.left : element.initializer; 1381 1382 if (ts.isIdentifier(target) || 1383 ts.isElementAccessExpression(target)) { 1384 continue; 1385 } 1386 1387 if (ts.isPropertyAccessExpression(target)) { 1388 if (target.questionDotToken) { 1389 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1390 } 1391 continue; 1392 } 1393 1394 if (ts.isObjectLiteralExpression(target) || ts.isArrayLiteralExpression(target)) { 1395 checkDestructuringAssignmentLhs(target); 1396 continue; 1397 } 1398 1399 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1400 } 1401 1402 if (ts.isShorthandPropertyAssignment(element)) { 1403 let name = jshelpers.getTextOfIdentifierOrLiteral(element.name); 1404 1405 if (name == MandatoryArguments || name == "eval") { 1406 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1407 } 1408 1409 continue; 1410 } 1411 1412 if (ts.isMethodDeclaration(element) || 1413 ts.isGetAccessorDeclaration(element) || 1414 ts.isSetAccessorDeclaration(element)) { 1415 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1416 } 1417 } 1418 } 1419} 1420 1421function checkBindingPattern(node: ts.BindingPattern) { 1422 let elements = node.elements; 1423 1424 for (let i = 0; i < elements.length; i++) { 1425 let element = elements[i]; 1426 1427 if (ts.isOmittedExpression(element)) { 1428 continue; 1429 } 1430 1431 if (element.dotDotDotToken) { 1432 let file = getSourceFileOfNode(node); 1433 1434 if (i != elements.length - 1) { 1435 throw new DiagnosticError(element, DiagnosticCode.A_rest_element_must_be_last_in_a_destructuring_pattern, file); 1436 } 1437 1438 if (element.initializer) { 1439 throw new DiagnosticError(element, DiagnosticCode.A_rest_parameter_cannot_have_an_initializer); 1440 } 1441 } 1442 } 1443} 1444