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): void { 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): void { 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): void { 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>): void { 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): boolean { 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): boolean { 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): void { 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): string[] { 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): void { 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): void { 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): void { 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): void { 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): void { 273 checkSyntaxErrorForSloppyAndStrictMode(node); 274 if (isStrictMode(node) || CmdOptions.isModules()) { 275 checkSyntaxErrorForStrictMode(node, scope); 276 } 277} 278 279function checkBreakOrContinueStatement(node: ts.BreakOrContinueStatement): boolean { 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, 306 jshelpers.getSourceFileOfNode(curNode)); 307 } 308 309 return; 310 } 311 break; 312 } 313 default: { 314 if (jshelpers.isIterationStatement(curNode, /*lookInLabeledStatement*/ false) && !node.label) { 315 // unlabeled break or continue within iteration statement - ok 316 return false; 317 } 318 break; 319 } 320 } 321 322 curNode = curNode.parent; 323 } 324 325 let diagnosticCode; 326 327 if (node.label) { 328 if (node.kind === ts.SyntaxKind.BreakStatement) { 329 diagnosticCode = DiagnosticCode.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement; 330 } else { 331 diagnosticCode = DiagnosticCode.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement; 332 } 333 } else { 334 if (node.kind === ts.SyntaxKind.BreakStatement) { 335 diagnosticCode = DiagnosticCode.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement; 336 } else { 337 diagnosticCode = DiagnosticCode.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement; 338 } 339 } 340 341 throw new DiagnosticError(node, diagnosticCode, jshelpers.getSourceFileOfNode(node)); 342} 343 344function checkReturnStatement(node: ts.ReturnStatement): void { 345 let func = jshelpers.getContainingFunction(node); 346 if (!func) { 347 let file = jshelpers.getSourceFileOfNode(node); 348 throw new DiagnosticError(node, DiagnosticCode.A_return_statement_can_only_be_used_within_a_function_body, file); 349 } 350} 351 352function checkMetaProperty(node: ts.MetaProperty): void { 353 let text = jshelpers.getTextOfIdentifierOrLiteral(node.name); 354 let file = jshelpers.getSourceFileOfNode(node); 355 switch (node.keywordToken) { 356 case ts.SyntaxKind.NewKeyword: { 357 let args = [text, jshelpers.tokenToString(node.keywordToken), "target"]; 358 if (text != "target") { 359 throw new DiagnosticError(node, DiagnosticCode._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, file, args); 360 } 361 362 let func = getContainingFunctionDeclaration(node); 363 if (!func) { 364 throw new DiagnosticError(node, 365 DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); 366 } else { 367 if (ts.isMethodDeclaration(func)) { 368 throw new DiagnosticError(node, 369 DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); 370 } 371 if (ts.isArrowFunction(func) && !jshelpers.getNewTargetContainer(node)) { 372 throw new DiagnosticError(node, 373 DiagnosticCode.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, file, args); 374 } 375 } 376 break; 377 } 378 case ts.SyntaxKind.ImportKeyword: { 379 if (text != "meta") { 380 let args = [text, jshelpers.tokenToString(node.keywordToken), "meta"]; 381 throw new DiagnosticError(node, DiagnosticCode._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, file, args); 382 } 383 break; 384 } 385 default: 386 break; 387 } 388} 389 390function checkNameInLetOrConstDeclarations(name: ts.Identifier | ts.BindingPattern): void { 391 if (name.kind === ts.SyntaxKind.Identifier) { 392 if (name.originalKeywordKind === ts.SyntaxKind.LetKeyword) { 393 let file = jshelpers.getSourceFileOfNode(name); 394 throw new DiagnosticError(name, DiagnosticCode.The_let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations, file); 395 } 396 } else { 397 let elements = name.elements; 398 for (let element of elements) { 399 if (!ts.isOmittedExpression(element)) { 400 checkNameInLetOrConstDeclarations(element.name); 401 } 402 } 403 } 404} 405 406function checkDisallowedLetOrConstStatement(node: ts.VariableStatement): void { 407 if (allowLetAndConstDeclarations(node.parent)) { 408 return; 409 } 410 411 if (jshelpers.isLet(node.declarationList)) { 412 throw new DiagnosticError(node, DiagnosticCode.The_let_declarations_can_only_be_declared_inside_a_block); 413 } 414 415 if (jshelpers.isVarConst(node.declarationList)) { 416 throw new DiagnosticError(node, DiagnosticCode.The_const_declarations_can_only_be_declared_inside_a_block); 417 } 418} 419 420function checkVariableDeclaration(node: ts.VariableDeclaration): void { 421 let file = jshelpers.getSourceFileOfNode(node); 422 if (!ts.isForInStatement(node.parent.parent) && !ts.isForOfStatement(node.parent.parent) && !ts.isCatchClause(node.parent)) { 423 if (!node.initializer) { 424 if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) { 425 throw new DiagnosticError(node, DiagnosticCode.A_destructuring_declaration_must_have_an_initializer, file); 426 } 427 428 if (jshelpers.isVarConst(node)) { 429 throw new DiagnosticError(node, DiagnosticCode.The_const_declarations_must_be_initialized, file); 430 } 431 } 432 } 433 434 if (node.exclamationToken && (node.parent.parent.kind !== ts.SyntaxKind.VariableStatement || !node.type || node.initializer)) { 435 if (node.initializer) { 436 throw new DiagnosticError(node.exclamationToken, 437 DiagnosticCode.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions, file); 438 } else { 439 throw new DiagnosticError(node.exclamationToken, 440 DiagnosticCode.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations, file); 441 } 442 } 443 444 if (jshelpers.isLet(node) || jshelpers.isVarConst(node)) { 445 checkNameInLetOrConstDeclarations(node.name); 446 if (!isInBlockScope(node.parent.parent.parent) && 447 !ts.isForInStatement(node.parent.parent) && 448 !ts.isForOfStatement(node.parent.parent) && 449 !ts.isForStatement(node.parent.parent)) { 450 throw new DiagnosticError(node, DiagnosticCode.const_and_let_declarations_not_allowed_in_statement_positions, file); 451 } 452 } 453} 454 455function checkDecorators(node: ts.Node): void { 456 if (!node.decorators) { 457 return; 458 } 459 460 let file = jshelpers.getSourceFileOfNode(node); 461 if (!jshelpers.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { 462 if (ts.isMethodDeclaration(node) && !jshelpers.nodeIsPresent((<ts.MethodDeclaration>node).body)) { 463 throw new DiagnosticError(node, DiagnosticCode.A_decorator_can_only_decorate_a_method_implementation_not_an_overload, file); 464 } else { 465 throw new DiagnosticError(node, DiagnosticCode.Decorators_are_not_valid_here, file); 466 } 467 } else if (ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node)) { 468 let accessors = jshelpers.getAllAccessorDeclarations((<ts.ClassDeclaration>node.parent).members, <ts.AccessorDeclaration>node); 469 if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) { 470 throw new DiagnosticError(node, DiagnosticCode.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name, file); 471 } 472 } 473} 474 475function checkAsyncModifier(node: ts.Node, asyncModifier: ts.Node): void { 476 switch (node.kind) { 477 case ts.SyntaxKind.ArrowFunction: 478 case ts.SyntaxKind.FunctionDeclaration: 479 case ts.SyntaxKind.FunctionExpression: 480 case ts.SyntaxKind.MethodDeclaration: 481 return; 482 default: 483 break; 484 } 485 let file = jshelpers.getSourceFileOfNode(node); 486 throw new DiagnosticError(asyncModifier, DiagnosticCode._0_modifier_cannot_be_used_here, file, ["async"]); 487} 488 489function checkModifiers(node: ts.Node): void { 490 if (!node.modifiers) { 491 return; 492 } 493 494 let lastStatic: ts.Node | undefined; 495 let lastDeclare: ts.Node | undefined; 496 let lastAsync: ts.Node | undefined; 497 let lastReadonly: ts.Node | undefined; 498 let flags = ts.ModifierFlags.None; 499 let file = jshelpers.getSourceFileOfNode(node); 500 501 for (let modifier of node.modifiers!) { 502 if (modifier.kind !== ts.SyntaxKind.ReadonlyKeyword) { 503 if (ts.isPropertySignature(node) || ts.isMethodSignature(node)) { 504 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_type_member, 505 file, [jshelpers.tokenToString(modifier.kind)]); 506 } 507 if (ts.isIndexSignatureDeclaration(node)) { 508 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_an_index_signature, 509 file, [jshelpers.tokenToString(modifier.kind)]); 510 } 511 } 512 switch (modifier.kind) { 513 case ts.SyntaxKind.ConstKeyword: { 514 if (ts.isEnumDeclaration(node)) { 515 throw new DiagnosticError(node, DiagnosticCode.A_class_member_cannot_have_the_0_keyword, 516 file, [jshelpers.tokenToString(ts.SyntaxKind.ConstKeyword)]); 517 } 518 break; 519 } 520 case ts.SyntaxKind.PublicKeyword: 521 case ts.SyntaxKind.ProtectedKeyword: 522 case ts.SyntaxKind.PrivateKeyword: { 523 const text = visibilityToString(jshelpers.modifierToFlag(modifier.kind)); 524 525 if (flags & ts.ModifierFlags.AccessibilityModifier) { 526 throw new DiagnosticError(modifier, DiagnosticCode.Accessibility_modifier_already_seen, file); 527 } else if (flags & ts.ModifierFlags.Static) { 528 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "static"]); 529 } else if (flags & ts.ModifierFlags.Readonly) { 530 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "readonly"]); 531 } else if (flags & ts.ModifierFlags.Async) { 532 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "async"]); 533 } else if (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent)) { 534 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_or_namespace_element, file, [text]); 535 } else if (flags & ts.ModifierFlags.Abstract) { 536 if (modifier.kind === ts.SyntaxKind.PrivateKeyword) { 537 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, [text, "abstract"]); 538 } else { 539 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, [text, "abstract"]); 540 } 541 } else if (ts.isPropertyDeclaration(node) && ts.isPrivateIdentifier(node.name)) { 542 throw new DiagnosticError(modifier, DiagnosticCode.An_accessibility_modifier_cannot_be_used_with_a_private_identifier, file); 543 } 544 flags |= jshelpers.modifierToFlag(modifier.kind); 545 break; 546 } 547 case ts.SyntaxKind.StaticKeyword: { 548 if (flags & ts.ModifierFlags.Static) { 549 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["static"]); 550 } else if (flags & ts.ModifierFlags.Readonly) { 551 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["static", "readonly"]); 552 } else if (flags & ts.ModifierFlags.Async) { 553 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["static", "async"]); 554 } else if (ts.isModuleBlock(node.parent) || ts.isSourceFile(node.parent)) { 555 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_or_namespace_element, file, ["static"]); 556 } else if (ts.isParameter(node)) { 557 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["static"]); 558 } else if (flags & ts.ModifierFlags.Abstract) { 559 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["static", "abstract"]); 560 } else if (ts.isPropertyDeclaration(node) && ts.isPrivateIdentifier(node.name)) { 561 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_a_private_identifier, file, ["static"]); 562 } 563 flags |= ts.ModifierFlags.Static; 564 lastStatic = modifier; 565 break; 566 } 567 case ts.SyntaxKind.ReadonlyKeyword: { 568 if (flags & ts.ModifierFlags.Readonly) { 569 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["readonly"]); 570 } else if (!ts.isPropertyDeclaration(node) && !ts.isPropertySignature(node) && 571 !ts.isIndexSignatureDeclaration(node) && !ts.isParameter(node)) { 572 // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. 573 throw new DiagnosticError(modifier, 574 DiagnosticCode.The_readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature, file); 575 } 576 flags |= ts.ModifierFlags.Readonly; 577 lastReadonly = modifier; 578 break; 579 } 580 case ts.SyntaxKind.ExportKeyword: { 581 if (flags & ts.ModifierFlags.Export) { 582 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["export"]); 583 } else if (flags & ts.ModifierFlags.Ambient) { 584 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "declare"]); 585 } else if (flags & ts.ModifierFlags.Abstract) { 586 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "abstract"]); 587 } else if (flags & ts.ModifierFlags.Async) { 588 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_must_precede_1_modifier, file, ["export", "async"]); 589 } else if (ts.isClassLike(node.parent)) { 590 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_class_elements_of_this_kind, file, ["export"]); 591 } else if (ts.isParameter(node)) { 592 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["export"]); 593 } 594 flags |= ts.ModifierFlags.Export; 595 break; 596 } 597 case ts.SyntaxKind.DefaultKeyword: { 598 let container = ts.isSourceFile(node.parent) ? node.parent : node.parent.parent; 599 if (ts.isModuleDeclaration(container) && !jshelpers.isAmbientModule(container)) { 600 throw new DiagnosticError(modifier, DiagnosticCode.A_default_export_can_only_be_used_in_an_ECMAScript_style_module, file); 601 } 602 603 flags |= ts.ModifierFlags.Default; 604 break; 605 } 606 case ts.SyntaxKind.DeclareKeyword: { 607 if (flags & ts.ModifierFlags.Ambient) { 608 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["declare"]); 609 } else if (flags & ts.ModifierFlags.Async) { 610 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_in_an_ambient_context, file, ["async"]); 611 } else if (ts.isClassLike(node.parent) && !ts.isPropertyDeclaration(node)) { 612 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_class_elements_of_this_kind, file, ["declare"]); 613 } else if (ts.isParameter(node)) { 614 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["declare"]); 615 } else if (ts.isPropertyDeclaration(node) && ts.isPrivateIdentifier(node.name)) { 616 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_a_private_identifier, file, ["declare"]); 617 } 618 flags |= ts.ModifierFlags.Ambient; 619 lastDeclare = modifier; 620 break; 621 } 622 case ts.SyntaxKind.AbstractKeyword: { 623 if (flags & ts.ModifierFlags.Abstract) { 624 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["abstract"]); 625 } 626 if (ts.isClassDeclaration(node) && ts.isConstructorTypeNode(node)) { 627 if (!ts.isMethodDeclaration(node) && !ts.isPropertyDeclaration(node) && 628 !ts.isGetAccessorDeclaration(node) && !ts.isSetAccessorDeclaration(node)) { 629 throw new DiagnosticError(modifier, 630 DiagnosticCode.The_abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration, file); 631 } 632 if (flags & ts.ModifierFlags.Static) { 633 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["static", "abstract"]); 634 } 635 if (flags & ts.ModifierFlags.Private) { 636 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["private", "abstract"]); 637 } 638 if (flags & ts.ModifierFlags.Async && lastAsync) { 639 throw new DiagnosticError(lastAsync, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["async", "abstract"]); 640 } 641 } 642 let name = (<ts.NamedDeclaration>node).name; 643 if (name && ts.isPrivateIdentifier(name)) { 644 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_a_private_identifier, file, ["abstract"]); 645 } 646 647 flags |= ts.ModifierFlags.Abstract; 648 break; 649 } 650 case ts.SyntaxKind.AsyncKeyword: { 651 if (flags & ts.ModifierFlags.Async) { 652 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_already_seen, file, ["async"]); 653 } else if (flags & ts.ModifierFlags.Ambient) { 654 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_in_an_ambient_context, file, ["async"]); 655 } else if (ts.isParameter(node)) { 656 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, file, ["async"]); 657 } 658 if (flags & ts.ModifierFlags.Abstract) { 659 throw new DiagnosticError(modifier, DiagnosticCode._0_modifier_cannot_be_used_with_1_modifier, file, ["async", "abstract"]); 660 } 661 flags |= ts.ModifierFlags.Async; 662 lastAsync = modifier; 663 break; 664 } 665 default: 666 break; 667 } 668 } 669 670 if (ts.isConstructorDeclaration(node)) { 671 if (flags & ts.ModifierFlags.Static) { 672 throw new DiagnosticError(lastStatic!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["static"]); 673 } 674 if (flags & ts.ModifierFlags.Abstract) { 675 throw new DiagnosticError(lastStatic!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["abstract"]); 676 } else if (flags & ts.ModifierFlags.Async) { 677 throw new DiagnosticError(lastAsync!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["async"]); 678 } else if (flags & ts.ModifierFlags.Readonly) { 679 throw new DiagnosticError(lastReadonly!, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, file, ["readonly"]); 680 } 681 } else if ((ts.isImportDeclaration(node) || ts.isImportEqualsDeclaration(node)) && flags & ts.ModifierFlags.Ambient) { 682 throw new DiagnosticError(lastDeclare!, DiagnosticCode.A_0_modifier_cannot_be_used_with_an_import_declaration, file, ["declare"]); 683 } else if (ts.isParameter(node) && (flags & ts.ModifierFlags.ParameterPropertyModifier) && isBindingPattern((<ts.ParameterDeclaration>node).name)) { 684 throw new DiagnosticError(node, DiagnosticCode.A_parameter_property_may_not_be_declared_using_a_binding_pattern, file); 685 } else if (ts.isParameter(node) && (flags & ts.ModifierFlags.ParameterPropertyModifier) && (<ts.ParameterDeclaration>node).dotDotDotToken) { 686 throw new DiagnosticError(node, DiagnosticCode.A_parameter_property_cannot_be_declared_using_a_rest_parameter, file); 687 } 688 689 if (flags & ts.ModifierFlags.Async) { 690 checkAsyncModifier(node, lastAsync!); 691 } 692} 693 694function checkVariableDeclarationList(declarationList: ts.VariableDeclarationList): void { 695 let declarations = declarationList.declarations; 696 if (!declarations.length) { 697 throw new DiagnosticError(declarationList, DiagnosticCode.Identifier_expected); 698 } 699 700 let decl = declarations[0].name; 701 if (isBindingPattern(decl)) { 702 checkBindingPattern(<ts.BindingPattern>decl); 703 } 704} 705 706function checkVariableStatement(node: ts.VariableStatement): void { 707 checkDecorators(node); 708 checkModifiers(node); 709 checkVariableDeclarationList(node.declarationList); 710 checkDisallowedLetOrConstStatement(node); 711} 712 713function checkForInOrForOfStatement(stmt: ts.ForInOrOfStatement): void { 714 let file = jshelpers.getSourceFileOfNode(stmt); 715 let leftExpr = stmt.initializer; 716 if (ts.isParenthesizedExpression(leftExpr)) { 717 leftExpr = findInnerExprOfParenthesis(leftExpr); 718 } 719 if (ts.isVariableDeclarationList(leftExpr)) { 720 let variableList = <ts.VariableDeclarationList>leftExpr; 721 checkVariableDeclarationList(variableList); 722 let declarations = variableList.declarations; 723 724 if (declarations.length > 1) { 725 if (ts.isForInStatement(stmt)) { 726 throw new DiagnosticError(variableList.declarations[1], 727 DiagnosticCode.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement, file); 728 } else { 729 throw new DiagnosticError(variableList.declarations[1], 730 DiagnosticCode.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement, file); 731 } 732 } 733 734 if (declarations[0].initializer) { 735 if (ts.isForInStatement(stmt)) { 736 throw new DiagnosticError(declarations[0].name, 737 DiagnosticCode.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer, file); 738 } else { 739 throw new DiagnosticError(declarations[0].name, 740 DiagnosticCode.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer, file); 741 } 742 } 743 744 if (declarations[0].type) { 745 if (ts.isForInStatement(stmt)) { 746 throw new DiagnosticError(declarations[0], 747 DiagnosticCode.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation, file); 748 } else { 749 throw new DiagnosticError(declarations[0], 750 DiagnosticCode.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation, file); 751 } 752 } 753 } else { 754 isInVaildAssignmentLeftSide(<ts.Expression>leftExpr); 755 756 if (ts.isArrayLiteralExpression(leftExpr) || ts.isObjectLiteralExpression(leftExpr)) { 757 checkDestructuringAssignmentLhs(leftExpr); 758 } 759 } 760} 761 762function checkForInOrForOfVariableDeclaration(iterationStatement: ts.ForInOrOfStatement): void { 763 let variableDeclarationList = <ts.VariableDeclarationList>iterationStatement.initializer; 764 // checkGrammarForInOrForOfStatement will check that there is exactly one declaration. 765 if (variableDeclarationList.declarations.length >= 1) { 766 checkVariableDeclaration(variableDeclarationList.declarations[0]); 767 } 768} 769 770function checkForInStatement(node: ts.ForInStatement): void { 771 checkForInOrForOfStatement(node); 772 773 let file = jshelpers.getSourceFileOfNode(node); 774 // for (let VarDecl in Expr) Statement 775 if (ts.isVariableDeclarationList(node.initializer)) { 776 checkForInOrForOfVariableDeclaration(node); 777 } else { 778 let varExpr = node.initializer; 779 if (ts.isArrayLiteralExpression(varExpr) || ts.isObjectLiteralExpression(varExpr)) { 780 throw new DiagnosticError(varExpr, DiagnosticCode.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern, file); 781 } 782 } 783} 784 785const enum OuterExpressionKinds { 786 PARENTHESES = 1 << 0, 787 TYPEASSERTIONS = 1 << 1, 788 NON_NULL_ASSERTIONS= 1 << 2, 789 PARTIALLY_EMITTED_EXPRESSIONS = 1 << 3, 790 ASSERTIONS= TYPEASSERTIONS | NON_NULL_ASSERTIONS, 791 ALL = PARENTHESES | ASSERTIONS | PARTIALLY_EMITTED_EXPRESSIONS 792} 793 794function checkReferenceExpression(expr: ts.Expression, invalidReferenceCode: DiagnosticCode, invalidOptionalChainCode: DiagnosticCode): void { 795 let node = jshelpers.skipOuterExpressions(expr, OuterExpressionKinds.ASSERTIONS | OuterExpressionKinds.PARENTHESES); 796 if (node.kind !== ts.SyntaxKind.Identifier && node.kind !== ts.SyntaxKind.PropertyAccessExpression && 797 node.kind !== ts.SyntaxKind.ElementAccessExpression) { 798 throw new DiagnosticError(expr, invalidReferenceCode); 799 } 800 801 if (node.flags & ts.NodeFlags.OptionalChain) { 802 throw new DiagnosticError(expr, invalidOptionalChainCode); 803 } 804} 805 806function checkReferenceAssignment(node: ts.Expression): void { 807 let invalidReferenceCode: DiagnosticCode; 808 let invalidOptionalChainCode: DiagnosticCode; 809 810 if (ts.isSpreadAssignment(node.parent)) { 811 invalidReferenceCode = DiagnosticCode.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access; 812 invalidOptionalChainCode = DiagnosticCode.The_target_of_an_object_rest_assignment_may_not_be_an_optional_property_access; 813 } else { 814 invalidReferenceCode = DiagnosticCode.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; 815 invalidOptionalChainCode = DiagnosticCode.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access; 816 } 817 818 checkReferenceExpression(node, invalidReferenceCode, invalidOptionalChainCode); 819} 820 821function checkDestructuringAssignment(node: ts.Expression | ts.ShorthandPropertyAssignment): void { 822 let target: ts.Expression; 823 if (ts.isShorthandPropertyAssignment(node)) { 824 let prop = <ts.ShorthandPropertyAssignment>node; 825 target = prop.name; 826 } else { 827 target = node; 828 } 829 830 if (ts.isBinaryExpression(target) && (<ts.BinaryExpression>target).operatorToken.kind === ts.SyntaxKind.EqualsToken) { 831 checkBinaryExpression(<ts.BinaryExpression>target); 832 target = (<ts.BinaryExpression>target).left; 833 } 834 835 if (ts.isObjectLiteralExpression(target)) { 836 checkObjectLiteralExpression(target); 837 } 838 839 checkReferenceAssignment(target); 840 841} 842 843function checkForOfStatement(node: ts.ForOfStatement): void { 844 checkForInOrForOfStatement(node); 845 846 if (ts.isVariableDeclarationList(node.initializer)) { 847 checkForInOrForOfVariableDeclaration(node); 848 } else { 849 let varExpr = node.initializer; 850 851 if (ts.isArrayLiteralExpression(varExpr) || ts.isObjectLiteralExpression(varExpr)) { 852 checkDestructuringAssignment(varExpr); 853 } else { 854 checkReferenceExpression( 855 varExpr, 856 DiagnosticCode.The_left_hand_side_of_a_for_of_statement_must_be_a_variable_or_a_property_access, 857 DiagnosticCode.The_left_hand_side_of_a_for_of_statement_may_not_be_an_optional_property_access); 858 } 859 } 860} 861 862function checkClassDeclaration(node: ts.ClassLikeDeclaration): void { 863 checkClassDeclarationHeritageClauses(node); 864 let hasConstructorImplementation = false; 865 let file = jshelpers.getSourceFileOfNode(node); 866 node.members.forEach(member => { 867 switch (member.kind) { 868 case ts.SyntaxKind.Constructor: { 869 if (hasConstructorImplementation) { 870 throw new DiagnosticError(node, DiagnosticCode.Multiple_constructor_implementations_are_not_allowed, file); 871 } else { 872 hasConstructorImplementation = true; 873 } 874 break; 875 } 876 case ts.SyntaxKind.MethodDeclaration: 877 case ts.SyntaxKind.SetAccessor: 878 checkFunctionLikeDeclaration(<ts.FunctionLikeDeclaration | ts.MethodSignature>member); 879 break; 880 case ts.SyntaxKind.GetAccessor: 881 checkGetAccessor(<ts.GetAccessorDeclaration>member); 882 break; 883 default: 884 break; 885 } 886 }); 887 888 // Class declaration not allowed in statement position 889 if (isStatement(node.parent.kind)) { 890 throw new DiagnosticError(node, DiagnosticCode.Class_declaration_not_allowed_in_statement_position, file); 891 } 892 893} 894 895function checkClassDeclarationHeritageClauses(node: ts.ClassLikeDeclaration): void { 896 let hasExtendsKeyWords = false; 897 checkDecorators(node); 898 checkModifiers(node); 899 if (node.heritageClauses === undefined) { 900 return; 901 } 902 903 let file = jshelpers.getSourceFileOfNode(node); 904 for (let heritageClause of node.heritageClauses) { 905 if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) { 906 if (hasExtendsKeyWords) { 907 throw new DiagnosticError(heritageClause, DiagnosticCode.The_extends_clause_already_seen, file); 908 } 909 910 if (heritageClause.types.length > 1) { 911 throw new DiagnosticError(heritageClause, DiagnosticCode.Classes_can_only_extend_a_single_class); 912 } 913 hasExtendsKeyWords = true; 914 } 915 } 916} 917 918function checkBinaryExpression(node: ts.BinaryExpression): void { 919 // AssignmentExpression 920 if (isAssignmentOperator(node.operatorToken.kind)) { 921 let leftExpr: ts.Expression = node.left; 922 if (ts.isParenthesizedExpression(leftExpr)) { 923 leftExpr = findInnerExprOfParenthesis(leftExpr); 924 } 925 926 if (node.operatorToken.kind === ts.SyntaxKind.EqualsToken) { 927 if (ts.isArrayLiteralExpression(leftExpr) || ts.isObjectLiteralExpression(leftExpr)) { 928 checkDestructuringAssignmentLhs(leftExpr); 929 } 930 } 931 932 isInVaildAssignmentLeftSide(leftExpr); 933 } 934} 935 936function isInVaildAssignmentLeftSide(leftExpr: ts.Expression): void { 937 if (jshelpers.isKeyword(leftExpr.kind) || 938 leftExpr.kind === ts.SyntaxKind.NumericLiteral || 939 leftExpr.kind === ts.SyntaxKind.StringLiteral) { 940 throw new DiagnosticError(leftExpr, DiagnosticCode.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access); 941 } 942} 943 944 945function checkContextualIdentifier(node: ts.Identifier): void { 946 if (jshelpers.isIdentifierName(node)) { 947 return; 948 } 949 950 let file = jshelpers.getSourceFileOfNode(node); 951 if (node.originalKeywordKind === ts.SyntaxKind.AwaitKeyword) { 952 if (jshelpers.isExternalOrCommonJsModule(file) && jshelpers.isInTopLevelContext(node)) { 953 throw new DiagnosticError(node, DiagnosticCode.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, 954 file, jshelpers.declarationNameToString(node)); 955 } else if (node.flags & ts.NodeFlags.AwaitContext) { 956 throw new DiagnosticError(node, DiagnosticCode.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, 957 file, jshelpers.declarationNameToString(node)); 958 } 959 } else if (node.originalKeywordKind === ts.SyntaxKind.YieldKeyword && node.flags & ts.NodeFlags.YieldContext) { 960 throw new DiagnosticError(node, DiagnosticCode.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, 961 file, jshelpers.declarationNameToString(node)); 962 } 963} 964 965function checkComputedPropertyName(node: ts.Node): void { 966 if (!ts.isComputedPropertyName(node)) { 967 return; 968 } 969 970 let expression = node.expression; 971 if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.CommaToken) { 972 let file = jshelpers.getSourceFileOfNode(node); 973 throw new DiagnosticError(expression, DiagnosticCode.A_comma_expression_is_not_allowed_in_a_computed_property_name, file); 974 } 975} 976 977const enum DeclarationMeaning { 978 GET_ACCESSOR = 1, 979 SET_ACCESSOR = 2, 980 PROPERTY_ASSIGNMENT = 4, 981 METHOD= 8, 982 GET_OR_SET_ACCESSOR = GET_ACCESSOR | SET_ACCESSOR, 983 PROPERTY_ASSIGNMENT_OR_METHOD = PROPERTY_ASSIGNMENT | METHOD, 984} 985 986function checkObjectLiteralExpression(node: ts.ObjectLiteralExpression): void { 987 let inDestructuring = jshelpers.isAssignmentTarget(node); 988 let file = jshelpers.getSourceFileOfNode(node); 989 let seen = new Map<ts.__String, DeclarationMeaning>(); 990 991 for (let prop of node.properties) { 992 if (ts.isSpreadAssignment(prop)) { 993 if (inDestructuring) { 994 let expression = jshelpers.skipParentheses(prop.expression); 995 if (ts.isArrayLiteralExpression(expression) || ts.isObjectLiteralExpression(expression)) { 996 throw new DiagnosticError(prop.expression, DiagnosticCode.A_rest_element_cannot_contain_a_binding_pattern, file); 997 } 998 } 999 continue; 1000 } 1001 let name = prop.name; 1002 if (ts.isComputedPropertyName(name)) { 1003 checkComputedPropertyName(name); 1004 } 1005 1006 if (ts.isShorthandPropertyAssignment(prop) && !inDestructuring && prop.objectAssignmentInitializer) { 1007 throw new DiagnosticError(prop.equalsToken!, 1008 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, 1009 file); 1010 } 1011 1012 if (ts.isPrivateIdentifier(name)) { 1013 throw new DiagnosticError(name, DiagnosticCode.Private_identifiers_are_not_allowed_outside_class_bodies, file); 1014 } 1015 1016 if (prop.modifiers) { 1017 for (let mod of prop.modifiers) { 1018 if (!ts.isMethodDeclaration(prop) || mod.kind != ts.SyntaxKind.AsyncKeyword) { 1019 throw new DiagnosticError(mod, DiagnosticCode._0_modifier_cannot_be_used_here, file, [jshelpers.getTextOfNode(mod)]); 1020 } 1021 } 1022 } 1023 1024 /** 1025 * It is a Syntax Error if PropertyNameList of PropertyDefinitionList contains any duplicate entries for "__proto__" and 1026 * at least two of those entries were obtained from productions of the form 1027 * PropertyDefinition : PropertyName : AssignmentExpression . 1028 */ 1029 let curKind = getPropertieDeclaration(prop, name); 1030 if (!curKind) { 1031 continue; 1032 } 1033 if (!inDestructuring) { 1034 let effectName = jshelpers.getPropertyNameForPropertyNameNode(name); 1035 if (!effectName || ts.isComputedPropertyName(name)) { 1036 continue; 1037 } 1038 let existKind = seen.get(effectName); 1039 if (!existKind) { 1040 seen.set(effectName, curKind); 1041 } else { 1042 if ((curKind & DeclarationMeaning.PROPERTY_ASSIGNMENT_OR_METHOD) && (existKind & DeclarationMeaning.PROPERTY_ASSIGNMENT_OR_METHOD)) { 1043 if (effectName === "___proto__") { 1044 throw new DiagnosticError(name, DiagnosticCode.Duplicate_identifier_0, file, [jshelpers.getTextOfNode(name)]); 1045 } 1046 } 1047 } 1048 } 1049 } 1050} 1051 1052function checkInvalidExclamationToken(exclamationToken: ts.ExclamationToken | undefined): void { 1053 if (!!exclamationToken) { 1054 let file = jshelpers.getSourceFileOfNode(exclamationToken); 1055 throw new DiagnosticError(exclamationToken, DiagnosticCode.A_definite_assignment_assertion_is_not_permitted_in_this_context, file); 1056 } 1057} 1058 1059function checkInvalidQuestionMark(questionToken: ts.QuestionToken | undefined): void { 1060 if (!!questionToken) { 1061 let file = jshelpers.getSourceFileOfNode(questionToken); 1062 throw new DiagnosticError(questionToken, DiagnosticCode.An_object_member_cannot_be_declared_optional, file); 1063 } 1064} 1065 1066// @ts-ignore 1067function getPropertieDeclaration(node: ts.Node, name: ts.Node): any { 1068 let decl = undefined; 1069 if (ts.isShorthandPropertyAssignment(node)) { 1070 checkInvalidExclamationToken(node.exclamationToken); 1071 } else if (ts.isPropertyAssignment(node)) { 1072 checkInvalidQuestionMark(node.questionToken); 1073 decl = DeclarationMeaning.PROPERTY_ASSIGNMENT; 1074 } else if (ts.isMethodDeclaration(node)) { 1075 decl = DeclarationMeaning.METHOD; 1076 } else if (ts.isGetAccessor(node)) { 1077 checkGetAccessor(node); 1078 decl = DeclarationMeaning.GET_ACCESSOR; 1079 } else if (ts.isSetAccessor(node)) { 1080 decl = DeclarationMeaning.SET_ACCESSOR; 1081 } else { 1082 LOGE("Unexpected syntax kind:" + node.kind); 1083 } 1084 return decl; 1085} 1086 1087function checkDisallowedTrailingComma(list: ts.NodeArray<ts.Node> | undefined): void { 1088 if (list && list.hasTrailingComma) { 1089 let file = jshelpers.getSourceFileOfNode(list[0]); 1090 throw new DiagnosticError(list[0], DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, file); 1091 } 1092} 1093 1094function checkParameters(parameters: ts.NodeArray<ts.ParameterDeclaration>): void { 1095 let count = parameters.length; 1096 let optionalParameter = false; 1097 1098 for (let i = 0; i < count; i++) { 1099 let parameter = parameters[i]; 1100 let file = jshelpers.getSourceFileOfNode(parameter); 1101 if (parameter.dotDotDotToken) { 1102 if (i != count - 1) { 1103 throw new DiagnosticError(parameter.dotDotDotToken, DiagnosticCode.A_rest_parameter_must_be_last_in_a_parameter_list, file); 1104 } 1105 1106 checkDisallowedTrailingComma(parameters); 1107 1108 if (parameter.initializer) { 1109 throw new DiagnosticError(parameter.name, DiagnosticCode.A_rest_parameter_cannot_have_an_initializer, file); 1110 } 1111 1112 if (parameter.questionToken) { 1113 throw new DiagnosticError(parameter.questionToken, DiagnosticCode.A_rest_parameter_cannot_be_optional, file); 1114 } 1115 1116 } else if (isOptionalParameter(parameter)) { 1117 optionalParameter = true; 1118 if (parameter.questionToken && parameter.initializer) { 1119 throw new DiagnosticError(parameter.name, DiagnosticCode.Parameter_cannot_have_question_mark_and_initializer, file); 1120 } 1121 } 1122 else if (optionalParameter && !parameter.initializer) { 1123 throw new DiagnosticError(parameter.name, DiagnosticCode.A_required_parameter_cannot_follow_an_optional_parameter, file); 1124 } 1125 } 1126} 1127 1128function checkArrowFunction(node: ts.Node): void { 1129 if (!ts.isArrowFunction(node)) { 1130 return; 1131 } 1132 1133 const { equalsGreaterThanToken } = node; 1134 let file = jshelpers.getSourceFileOfNode(node); 1135 const startLine = file.getLineAndCharacterOfPosition(equalsGreaterThanToken.pos).line; 1136 const endLine = file.getLineAndCharacterOfPosition(equalsGreaterThanToken.end).line; 1137 if (startLine !== endLine) { 1138 throw new DiagnosticError(equalsGreaterThanToken, DiagnosticCode.Line_terminator_not_permitted_before_arrow, file); 1139 } 1140} 1141 1142function checkFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration | ts.MethodSignature): void { 1143 checkDecorators(node); 1144 checkModifiers(node); 1145 checkParameters(node.parameters); 1146 checkArrowFunction(node); 1147} 1148 1149function checkLabeledStatement(node: ts.LabeledStatement): void { 1150 let file = jshelpers.getSourceFileOfNode(node); 1151 jshelpers.findAncestor(node.parent, current => { 1152 if (jshelpers.isFunctionLike(current)) { 1153 return "quit"; 1154 } 1155 1156 if (ts.isLabeledStatement(current) && (<ts.LabeledStatement>current).label.escapedText === node.label.escapedText) { 1157 throw new DiagnosticError(node.label, DiagnosticCode.Duplicate_label_0, file, [jshelpers.getTextOfNode(node.label)]); 1158 } 1159 return false; 1160 }); 1161 1162 let statement = node.statement; 1163 if (ts.isVariableStatement(statement)) { 1164 let variableStatement = <ts.VariableStatement>statement; 1165 if (jshelpers.isLet(variableStatement.declarationList)) { 1166 throw new DiagnosticError(node, DiagnosticCode.Lexical_declaration_let_not_allowed_in_statement_position); 1167 } 1168 1169 if (jshelpers.isVarConst(variableStatement.declarationList)) { 1170 throw new DiagnosticError(node, DiagnosticCode.Lexical_declaration_const_not_allowed_in_statement_position); 1171 } 1172 } 1173} 1174 1175function checkGetAccessor(node: ts.GetAccessorDeclaration): void { 1176 checkFunctionLikeDeclaration(node); 1177 if (node.parameters.length != 0) { 1178 throw new DiagnosticError(node, DiagnosticCode.Getter_must_not_have_any_formal_parameters); 1179 } 1180} 1181 1182function isValidUseSuperExpression(node: ts.Node, isCallExpression: boolean): boolean { 1183 if (!node) { 1184 return false; 1185 } 1186 1187 if (isCallExpression) { 1188 return ts.isConstructorDeclaration(node); 1189 } 1190 1191 if (!ts.isClassLike(node.parent) && !ts.isObjectLiteralExpression(node.parent)) { 1192 return false; 1193 } 1194 1195 return ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node) || 1196 ts.isPropertyDeclaration(node) || ts.isPropertySignature(node) || ts.isConstructorDeclaration(node); 1197} 1198 1199function checkSuperExpression(node: ts.SuperExpression): void { 1200 let file = jshelpers.getSourceFileOfNode(node); 1201 let isCallExpression = false; 1202 if (ts.isCallExpression(node.parent) && (<ts.CallExpression>node.parent).expression === node) { 1203 isCallExpression = true; 1204 } 1205 1206 let container = jshelpers.getSuperContainer(node, true); 1207 1208 if (!isCallExpression) { 1209 while (container && ts.isArrowFunction(container)) { 1210 container = jshelpers.getSuperContainer(container, true); 1211 } 1212 } 1213 1214 let isSuperExpCanUse = isValidUseSuperExpression(container, isCallExpression); 1215 1216 if (!isSuperExpCanUse) { 1217 let current = jshelpers.findAncestor(node, n => n === container ? "quit" : ts.isComputedPropertyName(n)); 1218 if (current && ts.isComputedPropertyName(current)) { 1219 throw new DiagnosticError(node, DiagnosticCode.The_super_cannot_be_referenced_in_a_computed_property_name, file); 1220 } 1221 let containerFunc = jshelpers.findAncestor(node, ts.isConstructorDeclaration); 1222 if (containerFunc) { 1223 return; 1224 } 1225 if (isCallExpression) { 1226 throw new DiagnosticError(node, 1227 DiagnosticCode.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors, file); 1228 } 1229 1230 if (!container || !container.parent || !ts.isClassLike(container.parent) || ts.isObjectLiteralExpression(container.parent)) { 1231 throw new DiagnosticError(node, 1232 DiagnosticCode.The_super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions, file); 1233 } 1234 1235 throw new DiagnosticError(node, 1236 DiagnosticCode.The_super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class, file); 1237 } 1238} 1239 1240function checkImportExpression(node: ts.ImportExpression): void { 1241 let args = (<ts.CallExpression>node.parent).arguments; 1242 if (args.length != 1) { 1243 throw new DiagnosticError(node, DiagnosticCode.Dynamic_imports_can_only_accept_a_module_specifier_optional_assertion_is_not_supported_yet); 1244 } 1245 1246 args.forEach(arg => { 1247 if (ts.isSpreadElement(arg)) { 1248 throw new DiagnosticError(node, DiagnosticCode.Argument_of_dynamic_import_cannot_be_spread_element); 1249 } 1250 }); 1251} 1252 1253function checkRegularExpression(regexp: ts.RegularExpressionLiteral): void { 1254 let regexpText = regexp.text; 1255 let regexpParse = require("regexpp").RegExpParser; 1256 new regexpParse().parseLiteral(regexpText); 1257} 1258 1259function checkThrowStatement(node: ts.ThrowStatement): void { 1260 if (ts.isIdentifier(node.expression) && (<ts.Identifier>node.expression).text === '') { 1261 throw new DiagnosticError(node, DiagnosticCode.Line_break_not_permitted_here, jshelpers.getSourceFileOfNode(node)); 1262 } 1263} 1264 1265function checkSyntaxErrorForSloppyAndStrictMode(node: ts.Node): void { 1266 switch (node.kind) { 1267 case ts.SyntaxKind.BreakStatement: 1268 case ts.SyntaxKind.ContinueStatement: 1269 checkBreakOrContinueStatement(<ts.BreakOrContinueStatement>node); 1270 break; 1271 case ts.SyntaxKind.ReturnStatement: 1272 checkReturnStatement(<ts.ReturnStatement>node); 1273 break; 1274 case ts.SyntaxKind.ComputedPropertyName: 1275 checkComputedPropertyName(<ts.ComputedPropertyName>node); 1276 break; 1277 case ts.SyntaxKind.ObjectBindingPattern: 1278 case ts.SyntaxKind.ArrayBindingPattern: 1279 checkBindingPattern(<ts.BindingPattern>node); 1280 break; 1281 case ts.SyntaxKind.MetaProperty: 1282 checkMetaProperty(<ts.MetaProperty>node); 1283 break; 1284 case ts.SyntaxKind.VariableDeclaration: 1285 checkVariableDeclaration(<ts.VariableDeclaration>node); 1286 break; 1287 case ts.SyntaxKind.VariableStatement: 1288 checkVariableStatement(<ts.VariableStatement>node); 1289 break; 1290 case ts.SyntaxKind.ForInStatement: 1291 checkForInStatement(<ts.ForInStatement>node); 1292 break; 1293 case ts.SyntaxKind.ForOfStatement: 1294 checkForOfStatement(<ts.ForOfStatement>node); 1295 break; 1296 case ts.SyntaxKind.ClassDeclaration: 1297 case ts.SyntaxKind.ClassExpression: 1298 checkClassDeclaration(<ts.ClassLikeDeclaration>node); 1299 break; 1300 case ts.SyntaxKind.SuperKeyword: 1301 checkSuperExpression(<ts.SuperExpression>node); 1302 break; 1303 case ts.SyntaxKind.ImportKeyword: 1304 checkImportExpression(<ts.ImportExpression>node); 1305 break; 1306 case ts.SyntaxKind.BinaryExpression: 1307 checkBinaryExpression(<ts.BinaryExpression>node); 1308 break; 1309 case ts.SyntaxKind.Identifier: 1310 checkContextualIdentifier(<ts.Identifier>node); 1311 break; 1312 case ts.SyntaxKind.ObjectLiteralExpression: 1313 checkObjectLiteralExpression(<ts.ObjectLiteralExpression>node); 1314 break; 1315 case ts.SyntaxKind.FunctionDeclaration: 1316 case ts.SyntaxKind.MethodSignature: 1317 case ts.SyntaxKind.MethodDeclaration: 1318 case ts.SyntaxKind.SetAccessor: 1319 case ts.SyntaxKind.Constructor: 1320 case ts.SyntaxKind.FunctionExpression: 1321 case ts.SyntaxKind.ArrowFunction: 1322 checkFunctionLikeDeclaration(<ts.FunctionLikeDeclaration | ts.MethodSignature>node); 1323 break; 1324 case ts.SyntaxKind.GetAccessor: 1325 checkGetAccessor(<ts.GetAccessorDeclaration>node); 1326 break; 1327 case ts.SyntaxKind.LabeledStatement: 1328 checkLabeledStatement(<ts.LabeledStatement>node); 1329 break; 1330 case ts.SyntaxKind.RegularExpressionLiteral: 1331 checkRegularExpression(<ts.RegularExpressionLiteral>node); 1332 break; 1333 case ts.SyntaxKind.ThrowStatement: 1334 checkThrowStatement(<ts.ThrowStatement>node); 1335 break; 1336 default: 1337 break; 1338 } 1339} 1340 1341function checkDestructuringAssignmentLhs(lhs: ts.Expression): void { 1342 let file = getSourceFileOfNode(lhs); 1343 if (ts.isArrayLiteralExpression(lhs)) { 1344 let elements = lhs.elements; 1345 1346 for (let i = 0; i < elements.length; i++) { 1347 let target = elements[i]; 1348 1349 if (ts.isSpreadElement(target)) { 1350 if (i != elements.length - 1) { 1351 throw new DiagnosticError(target, DiagnosticCode.A_rest_element_must_be_last_in_a_destructuring_pattern, file); 1352 } 1353 1354 if (elements.hasTrailingComma) { 1355 throw new DiagnosticError(target, DiagnosticCode.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma, file); 1356 } 1357 1358 if (ts.isArrayLiteralExpression(target.expression) || ts.isObjectLiteralExpression(target.expression)) { 1359 checkDestructuringAssignmentLhs(target.expression); 1360 } 1361 1362 continue; 1363 } 1364 1365 target = ts.isBinaryExpression(target) ? target.left : target; 1366 1367 if (ts.isOmittedExpression(target) || ts.isElementAccessExpression(target)) { 1368 continue; 1369 } 1370 1371 if (ts.isIdentifier(target)) { 1372 let name = jshelpers.getTextOfIdentifierOrLiteral(target); 1373 1374 if (name === MandatoryArguments || name === "eval") { 1375 throw new DiagnosticError(target, DiagnosticCode.Property_destructuring_pattern_expected, file); 1376 } 1377 continue; 1378 } 1379 1380 if (ts.isPropertyAccessExpression(target)) { 1381 if (target.questionDotToken) { 1382 throw new DiagnosticError(target, DiagnosticCode.Property_destructuring_pattern_expected, file); 1383 } 1384 1385 continue; 1386 } 1387 1388 if (ts.isArrayLiteralExpression(target) || ts.isObjectLiteralExpression(target)) { 1389 checkDestructuringAssignmentLhs(target); 1390 continue; 1391 } 1392 1393 throw new DiagnosticError(target, DiagnosticCode.Property_destructuring_pattern_expected, file); 1394 } 1395 } 1396 1397 if (ts.isObjectLiteralExpression(lhs)) { 1398 let elements = lhs.properties; 1399 1400 for (let i = 0; i < elements.length; i++) { 1401 let element = elements[i]; 1402 1403 if (ts.isSpreadAssignment(element)) { 1404 if (i != elements.length - 1) { 1405 let file = getSourceFileOfNode(lhs); 1406 throw new DiagnosticError(element, DiagnosticCode.A_rest_element_must_be_last_in_a_destructuring_pattern, file); 1407 } 1408 continue; 1409 } 1410 1411 if (ts.isPropertyAssignment(element)) { 1412 let target = ts.isBinaryExpression(element.initializer) ? element.initializer.left : element.initializer; 1413 1414 if (ts.isIdentifier(target) || 1415 ts.isElementAccessExpression(target)) { 1416 continue; 1417 } 1418 1419 if (ts.isPropertyAccessExpression(target)) { 1420 if (target.questionDotToken) { 1421 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1422 } 1423 continue; 1424 } 1425 1426 if (ts.isObjectLiteralExpression(target) || ts.isArrayLiteralExpression(target)) { 1427 checkDestructuringAssignmentLhs(target); 1428 continue; 1429 } 1430 1431 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1432 } 1433 1434 if (ts.isShorthandPropertyAssignment(element)) { 1435 let name = jshelpers.getTextOfIdentifierOrLiteral(element.name); 1436 1437 if (name === MandatoryArguments || name === "eval") { 1438 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1439 } 1440 1441 continue; 1442 } 1443 1444 if (ts.isMethodDeclaration(element) || 1445 ts.isGetAccessorDeclaration(element) || 1446 ts.isSetAccessorDeclaration(element)) { 1447 throw new DiagnosticError(element, DiagnosticCode.Property_destructuring_pattern_expected, file); 1448 } 1449 } 1450 } 1451} 1452 1453function checkBindingPattern(node: ts.BindingPattern): void { 1454 let elements = node.elements; 1455 1456 for (let i = 0; i < elements.length; i++) { 1457 let element = elements[i]; 1458 1459 if (ts.isOmittedExpression(element)) { 1460 continue; 1461 } 1462 1463 if (element.dotDotDotToken) { 1464 let file = getSourceFileOfNode(node); 1465 1466 if (i != elements.length - 1) { 1467 throw new DiagnosticError(element, DiagnosticCode.A_rest_element_must_be_last_in_a_destructuring_pattern, file); 1468 } 1469 1470 if (element.initializer) { 1471 throw new DiagnosticError(element, DiagnosticCode.A_rest_parameter_cannot_have_an_initializer); 1472 } 1473 } 1474 } 1475} 1476