File indexing completed on 2024-04-14 04:31:14
0001 /* This file is part of KDevelop 0002 * 0003 * Copyright (C) 2011-2015 Miquel Sabaté Solà <mikisabate@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 */ 0018 0019 #include <parser/astvisitor.h> 0020 #include <parserdebug.h> 0021 0022 /* 0023 * Note that each visitor method has a comment that explains how the AST 0024 * is structured for the specific statement. Only the following attributes 0025 * will be considered: l, r, cond and ensure. If any of these pointers are not 0026 * specified, it means that its value is just nullptr. 0027 */ 0028 0029 using namespace ruby; 0030 0031 AstVisitor::~AstVisitor() 0032 { 0033 } 0034 0035 void AstVisitor::visitCode(Ast *node) 0036 { 0037 qCDebug(PARSER) << "Visiting Code..."; 0038 Node *aux = node->tree; 0039 0040 for (Node *n = aux; n; n = n->next) { 0041 visitNode(node); 0042 node->tree = n->next; 0043 } 0044 node->tree = aux; 0045 } 0046 0047 void AstVisitor::visitName(Ast *node) 0048 { 0049 Q_UNUSED(node) 0050 } 0051 0052 void AstVisitor::visitNumeric(Ast *node) 0053 { 0054 Q_UNUSED(node) 0055 } 0056 0057 void AstVisitor::visitRegexp(Ast *node) 0058 { 0059 Q_UNUSED(node) 0060 } 0061 0062 void AstVisitor::visitString(Ast *node) 0063 { 0064 /* 0065 * l -> list of variables contained inside the string (by using #{var}). 0066 */ 0067 0068 Node *n = node->tree; 0069 node->tree = n->l; 0070 visitStatements(node); 0071 node->tree = n; 0072 } 0073 0074 void AstVisitor::visitSymbol(Ast *node) 0075 { 0076 Q_UNUSED(node) 0077 } 0078 0079 void AstVisitor::visitBody(Ast *node) 0080 { 0081 /* 0082 * l -> list of inner statements. 0083 * r -> optional rescue statement. 0084 * cond -> optional else statement. 0085 * ensure -> optional ensure statement. 0086 */ 0087 0088 Node *n = node->tree; 0089 if (!n) { 0090 return; 0091 } 0092 0093 node->tree = n->l; 0094 visitStatements(node); 0095 node->tree = n->r; 0096 visitNode(node); 0097 node->tree = n->cond; 0098 visitNode(node); 0099 node->tree = n->ensure; 0100 visitNode(node); 0101 node->tree = n; 0102 } 0103 0104 void AstVisitor::visitBinary(Ast *node) 0105 { 0106 /* 0107 * l -> left operator. 0108 * r -> right operator. 0109 */ 0110 0111 Node *n = node->tree; 0112 node->tree = n->l; 0113 visitNode(node); 0114 node->tree = n->r; 0115 visitNode(node); 0116 node->tree = n; 0117 } 0118 0119 void AstVisitor::visitBoolean(Ast *node) 0120 { 0121 /* Same as for the visitBinary method */ 0122 0123 Node *n = node->tree; 0124 node->tree = n->l; 0125 visitNode(node); 0126 node->tree = n->r; 0127 visitNode(node); 0128 node->tree = n; 0129 } 0130 0131 void AstVisitor::visitRange(Ast *node) 0132 { 0133 /* Same as for the visitBinary method */ 0134 0135 Node *n = node->tree; 0136 node->tree = n->l; 0137 visitNode(node); 0138 node->tree = n->r; 0139 visitNode(node); 0140 node->tree = n; 0141 } 0142 0143 void AstVisitor::visitUnary(Ast *node) 0144 { 0145 /* 0146 * l -> the operator. 0147 */ 0148 0149 Node *n = node->tree; 0150 node->tree = n->l; 0151 visitNode(node); 0152 node->tree = n; 0153 } 0154 0155 void AstVisitor::visitArray(Ast *node) 0156 { 0157 /* 0158 * l -> list of statements (the items of the array). 0159 */ 0160 0161 Node *n = node->tree; 0162 node->tree = n->l; 0163 visitStatements(node); 0164 node->tree = n; 0165 } 0166 0167 void AstVisitor::visitArrayValue(Ast *node) 0168 { 0169 /* 0170 * l -> the node containing the Array object. 0171 * r -> the index expression. 0172 */ 0173 0174 Node *n = node->tree; 0175 node->tree = n->l; 0176 visitNode(node); 0177 node->tree = n->r; 0178 visitStatements(node); 0179 node->tree = n; 0180 } 0181 0182 void AstVisitor::visitHash(Ast *node) 0183 { 0184 /* 0185 * l -> list of hash items. 0186 */ 0187 0188 Node *n = node->tree; 0189 node->tree = n->l; 0190 for (; node->tree != nullptr; node->tree = node->tree->next) { 0191 visitBinary(node); 0192 } 0193 node->tree = n; 0194 } 0195 0196 void AstVisitor::visitReturnStatement(Ast *node) 0197 { 0198 /* 0199 * l -> the return expression. 0200 */ 0201 0202 Node *n = node->tree; 0203 node->tree = n->l; 0204 visitNode(node); 0205 node->tree = n; 0206 } 0207 0208 void AstVisitor::visitUndefStatement(Ast *node) 0209 { 0210 /* 0211 * r -> list of undef items. 0212 */ 0213 0214 Node *n = node->tree; 0215 node->tree = n->r; 0216 visitStatements(node); 0217 node->tree = n; 0218 } 0219 0220 void AstVisitor::visitAliasStatement(Ast *node) 0221 { 0222 /* Same as for the visitBinary method. */ 0223 0224 Node *n = node->tree; 0225 node->tree = n->l; 0226 visitNode(node); 0227 node->tree = n->r; 0228 visitNode(node); 0229 node->tree = n; 0230 } 0231 0232 void AstVisitor::visitYieldStatement(Ast *node) 0233 { 0234 /* 0235 * l -> the yield expression. 0236 */ 0237 Node *n = node->tree; 0238 node->tree = n->l; 0239 visitNode(node); 0240 node->tree = n; 0241 } 0242 0243 void AstVisitor::visitAssignmentStatement(Ast *node) 0244 { 0245 /* 0246 * l -> the left side of the assignment. 0247 * r -> the right side of the assignment. 0248 */ 0249 0250 Node *n = node->tree; 0251 node->tree = n->l; 0252 visitStatements(node); 0253 node->tree = n->r; 0254 visitStatements(node); 0255 node->tree = n; 0256 } 0257 0258 void AstVisitor::visitIfStatement(Ast *node) 0259 { 0260 /* 0261 * l -> list of inner statements. 0262 * r -> the "tail": optional list of elsif's and an optional else. 0263 * cond -> the condition expression. 0264 */ 0265 0266 Node *n = node->tree; 0267 node->tree = n->cond; 0268 visitNode(node); 0269 node->tree = n->l; 0270 visitStatements(node); 0271 node->tree = n->r; 0272 visitIfTail(node); 0273 node->tree = n; 0274 } 0275 0276 void AstVisitor::visitCaseStatement(Ast *node) 0277 { 0278 /* 0279 * l -> the case body: list of when statements and an optional else 0280 * statement at the end. 0281 * cond -> the condition expression. 0282 */ 0283 0284 Node *n = node->tree; 0285 node->tree = n->cond; 0286 visitNode(node); 0287 node->tree = n->l; 0288 visitWhenStatements(node); 0289 node->tree = n; 0290 } 0291 0292 void AstVisitor::visitBeginStatement(Ast *node) 0293 { 0294 /* 0295 * l -> the body of the begin statement. Note that this body is not just 0296 * a list of "regular" statement, check the visitBody method for more info. 0297 */ 0298 0299 Node *n = node->tree; 0300 node->tree = n->l; 0301 visitBody(node); 0302 node->tree = n; 0303 } 0304 0305 void AstVisitor::visitUpBeginEndStatement(Ast *node) 0306 { 0307 /* 0308 * l -> list of inner statements. 0309 */ 0310 0311 Node *n = node->tree; 0312 node->tree = n->l; 0313 visitStatements(node); 0314 node->tree = n; 0315 } 0316 0317 void AstVisitor::visitWhileStatement(Ast *node) 0318 { 0319 /* 0320 * l -> list of inner statements. 0321 * cond -> the condition expression. 0322 */ 0323 0324 Node *n = node->tree; 0325 node->tree = n->cond; 0326 visitNode(node); 0327 node->tree = n->l; 0328 visitStatements(node); 0329 node->tree = n; 0330 } 0331 0332 void AstVisitor::visitForStatement(Ast *node) 0333 { 0334 /* 0335 * l -> list of inner statements. 0336 * r -> list of variables declared before the "in" keyword. 0337 * cond -> the expression after the "in" keyword. 0338 */ 0339 0340 Node *n = node->tree; 0341 node->tree = n->r; 0342 visitStatements(node); 0343 node->tree = n->cond; 0344 visitNode(node); 0345 node->tree = n->l; 0346 visitStatements(node); 0347 node->tree = n; 0348 } 0349 0350 void AstVisitor::visitMethodStatement(Ast *node) 0351 { 0352 /* 0353 * l -> list of inner statements. 0354 * r -> list of method arguments. 0355 */ 0356 0357 Node *n = node->tree; 0358 if (!n) { 0359 return; 0360 } 0361 0362 node->tree = n->r; 0363 visitMethodArguments(node); 0364 node->tree = n->l; 0365 visitBody(node); 0366 node->tree = n; 0367 } 0368 0369 void AstVisitor::visitMethodArguments(Ast *node) 0370 { 0371 /* Just iterate over the "next" pointer. */ 0372 0373 Node *aux = node->tree; 0374 for (Node *n = aux; n != nullptr; n = n->next) { 0375 visitParameter(node); 0376 node->tree = n->next; 0377 } 0378 node->tree = aux; 0379 } 0380 0381 void AstVisitor::visitParameter(Ast *node) 0382 { 0383 Q_UNUSED(node) 0384 } 0385 0386 void AstVisitor::visitClassStatement(Ast *node) 0387 { 0388 /* 0389 * l -> the body of the class statement. Note that this body is not just 0390 * a list of "regular" statement, check the visitBody method for more info. 0391 * r -> the name of the class. 0392 * cond -> the superclass node. 0393 */ 0394 0395 Node *n = node->tree; 0396 node->tree = n->cond; 0397 visitNode(node); 0398 node->tree = n->l; 0399 visitBody(node); 0400 node->tree = n->r; 0401 visitClassName(node); 0402 node->tree = n; 0403 } 0404 0405 void AstVisitor::visitSingletonClass(Ast *node) 0406 { 0407 /* 0408 * l -> the body of the class statement. Note that this body is not just 0409 * a list of "regular" statement, check the visitBody method for more info. 0410 * r -> the expression after the lshift ("<<") operator. 0411 */ 0412 0413 Node *n = node->tree; 0414 node->tree = n->l; 0415 visitBody(node); 0416 node->tree = n->r; 0417 visitNode(node); 0418 node->tree = n; 0419 } 0420 0421 void AstVisitor::visitModuleStatement(Ast *node) 0422 { 0423 /* 0424 * l -> the body of the class statement. Note that this body is not just 0425 * a list of "regular" statement, check the visitBody method for more info. 0426 * r -> the name of the module. 0427 */ 0428 0429 Node *n = node->tree; 0430 node->tree = n->l; 0431 visitBody(node); 0432 node->tree = n->r; 0433 visitClassName(node); 0434 node->tree = n; 0435 } 0436 0437 void AstVisitor::visitMethodCall(Ast *node) 0438 { 0439 /* 0440 * l -> the caller (note that it's a list, i.e. A::B::foo). 0441 * r -> the arguments for this method call. 0442 * cond -> an optional Ruby block. 0443 */ 0444 0445 /* 0446 * Note that the l pointer can contain again another method call. 0447 * This happens for example here: 0448 * Class.new { def foo(a, b); end }.new.foo(1, 2) 0449 * In order to get everything straight, all builders end up 0450 * re-implementing this method. This is why this method has no 0451 * implementation by default. 0452 */ 0453 Q_UNUSED(node); 0454 } 0455 0456 void AstVisitor::visitSuper(Ast *node) 0457 { 0458 /* 0459 * r -> the arguments passed to the super call. 0460 */ 0461 0462 Node *n = node->tree; 0463 node->tree = n->r; 0464 for (Node *aux = n->r; aux != nullptr; aux = aux->next) { 0465 visitNode(node); 0466 node->tree = aux->next; 0467 } 0468 node->tree = n; 0469 } 0470 0471 void AstVisitor::visitLambda(Ast *node) 0472 { 0473 /* 0474 * cond -> the block of this lambda expression. 0475 */ 0476 0477 Node *n = node->tree; 0478 node->tree = n->cond; 0479 visitBlock(node); 0480 node->tree = n; 0481 } 0482 0483 void AstVisitor::visitBlock(Ast *node) 0484 { 0485 /* 0486 * l -> list of inner statements. 0487 * r -> list of block variables. 0488 */ 0489 0490 Node *aux = node->tree; 0491 if (!aux) { 0492 return; 0493 } 0494 node->tree = aux->r; 0495 visitBlockVariables(node); 0496 node->tree = aux->l; 0497 visitStatements(node); 0498 node->tree = aux; 0499 } 0500 0501 void AstVisitor::visitBlockVariables(Ast *node) 0502 { 0503 /* 0504 * Just iterate over the next pointer. 0505 */ 0506 0507 Node *aux = node->tree; 0508 for (Node *n = node->tree; n != nullptr; n = n->next) { 0509 visitNode(node); 0510 node->tree = n->next; 0511 } 0512 node->tree = aux; 0513 } 0514 0515 void AstVisitor::visitRequire(Ast *node, bool relative) 0516 { 0517 Q_UNUSED(node) 0518 Q_UNUSED(relative) 0519 } 0520 0521 void AstVisitor::visitMixin(Ast *node, bool include) 0522 { 0523 Q_UNUSED(node); 0524 Q_UNUSED(include); 0525 } 0526 0527 void AstVisitor::visitDefined(Ast *node) 0528 { 0529 /* 0530 * l -> the expression from the "defined" statement. 0531 */ 0532 0533 Node *n = node->tree; 0534 node->tree = n->l; 0535 visitNode(node); 0536 node->tree = n; 0537 } 0538 0539 void AstVisitor::visitTrue(Ast *node) 0540 { 0541 Q_UNUSED(node) 0542 } 0543 0544 void AstVisitor::visitFalse(Ast *node) 0545 { 0546 Q_UNUSED(node) 0547 } 0548 0549 void AstVisitor::visitNil(Ast *node) 0550 { 0551 Q_UNUSED(node) 0552 } 0553 0554 void AstVisitor::visitFile(Ast *node) 0555 { 0556 Q_UNUSED(node) 0557 } 0558 0559 void AstVisitor::visitLine(Ast *node) 0560 { 0561 Q_UNUSED(node) 0562 } 0563 0564 void AstVisitor::visitEncoding(Ast *node) 0565 { 0566 Q_UNUSED(node) 0567 } 0568 0569 void AstVisitor::visitSelf(Ast *node) 0570 { 0571 Q_UNUSED(node) 0572 } 0573 0574 void AstVisitor::visitAccessSpecifier(const access_t policy) 0575 { 0576 Q_UNUSED(policy) 0577 } 0578 0579 void AstVisitor::visitClassName(Ast *node) 0580 { 0581 Q_UNUSED(node); 0582 } 0583 0584 void AstVisitor::visitRescue(Ast *node) 0585 { 0586 /* 0587 * l -> rescue arg. 0588 * r -> list of inner statement. 0589 */ 0590 0591 Node *n = node->tree; 0592 node->tree = n->l; 0593 visitNode(node); 0594 node->tree = n->r; 0595 visitStatements(node); 0596 node->tree = n; 0597 } 0598 0599 void AstVisitor::visitRescueArg(Ast *node) 0600 { 0601 /* 0602 * l -> Left part of the rescue argument, could be a list. 0603 * r -> Right part of the rescue argument, only the DeclarationBuilder 0604 * wants to access this part. 0605 */ 0606 0607 Node *n = node->tree; 0608 node->tree = n->l; 0609 visitStatements(node); 0610 node->tree = n; 0611 } 0612 0613 void AstVisitor::visitEnsure(Ast *node) 0614 { 0615 /* 0616 * l -> The inner statements. 0617 */ 0618 0619 Node *n = node->tree; 0620 node->tree = n->l; 0621 visitStatements(node); 0622 node->tree = n; 0623 } 0624 0625 void AstVisitor::visitNode(Ast *node) 0626 { 0627 QByteArray name; 0628 Node *n = node->tree; 0629 0630 /* This is not a valid node */ 0631 if (!n || n->kind == token_invalid) { 0632 return; 0633 } 0634 switch (n->kind) { 0635 case token_return: visitReturnStatement(node); break; 0636 case token_yield: visitYieldStatement(node); break; 0637 case token_alias: visitAliasStatement(node); break; 0638 case token_undef: visitUndefStatement(node); break; 0639 case token_if: case token_unless: case token_ternary: 0640 visitIfStatement(node); 0641 break; 0642 case token_begin: visitBeginStatement(node); break; 0643 case token_up_begin: 0644 case token_up_end: visitUpBeginEndStatement(node); break; 0645 case token_case: visitCaseStatement(node); break; 0646 case token_while: case token_until: visitWhileStatement(node); break; 0647 case token_for: visitForStatement(node); break; 0648 case token_class: visitClassStatement(node); break; 0649 case token_singleton_class: visitSingletonClass(node); break; 0650 case token_module: visitModuleStatement(node); break; 0651 case token_function: visitMethodStatement(node); break; 0652 case token_super: visitSuper(node); break; 0653 case token_method_call: checkMethodCall(node); break; 0654 case token_assign: 0655 case token_op_assign: visitAssignmentStatement(node); break; 0656 case token_object: 0657 name = QByteArray(node->tree->name); 0658 if (name == "public") { 0659 if (declaredInContext(name)) { 0660 visitName(node); 0661 } else { 0662 visitAccessSpecifier(public_a); 0663 } 0664 } else if (name == "protected") { 0665 if (declaredInContext(name)) { 0666 visitName(node); 0667 } else { 0668 visitAccessSpecifier(protected_a); 0669 } 0670 } else if (name == "private") { 0671 if (declaredInContext(name)) { 0672 visitName(node); 0673 } else { 0674 visitAccessSpecifier(private_a); 0675 } 0676 } else { 0677 visitName(node); 0678 } 0679 break; 0680 case token_hash: visitHash(node); break; 0681 case token_array: visitArray(node); break; 0682 case token_array_value: visitArrayValue(node); break; 0683 case token_defined: visitDefined(node); break; 0684 case token_unary_plus: case token_unary_minus: case token_neg: 0685 case token_not: 0686 visitUnary(node); 0687 break; 0688 case token_plus: case token_minus: case token_mul: case token_div: 0689 case token_mod: case token_lshift: case token_rshift: case token_pow: 0690 visitBinary(node); 0691 break; 0692 case token_dot2: case token_dot3: 0693 visitRange(node); 0694 break; 0695 case token_cmp: case token_eq: case token_eqq: case token_match: 0696 case token_nmatch: case token_greater: case token_geq: 0697 case token_lesser: case token_leq: 0698 case token_or: case token_and: case token_kw_and: 0699 case token_kw_not: case token_kw_or: 0700 visitBoolean(node); 0701 break; 0702 case token_numeric: visitNumeric(node); break; 0703 case token_string: case token_heredoc: visitString(node); break; 0704 case token_regexp: visitRegexp(node); break; 0705 case token_nil: visitNil(node); break; 0706 case token_true: visitTrue(node); break; 0707 case token_false: visitFalse(node); break; 0708 case token_line: visitLine(node); break; 0709 case token_file: visitFile(node); break; 0710 case token_encoding: visitEncoding(node); break; 0711 case token_self: visitSelf(node); break; 0712 case token_symbol: case token_key: visitSymbol(node); break; 0713 case token_rescue: visitRescue(node); break; 0714 case token_rescue_arg: visitRescueArg(node); break; 0715 case token_ensure: visitEnsure(node); break; 0716 case token_break: case token__end__: case token_next: 0717 case token_redo: case token_retry: 0718 return; 0719 } 0720 } 0721 0722 void AstVisitor::visitStatements(Ast *list) 0723 { 0724 Node *aux = list->tree; 0725 for (Node *n = aux; n; n = n->next) { 0726 visitNode(list); 0727 list->tree = n->next; 0728 } 0729 list->tree = aux; 0730 } 0731 0732 void AstVisitor::visitIfTail(Ast *tail) 0733 { 0734 Node *n = tail->tree; 0735 if (!n) { 0736 return; 0737 } 0738 0739 /* Check if this is an elsif or an else statement */ 0740 if (!n->cond) { 0741 tail->tree = n->l; 0742 visitStatements(tail); 0743 } else { 0744 visitIfStatement(tail); 0745 } 0746 tail->tree = n; 0747 } 0748 0749 void AstVisitor::visitWhenStatements(Ast *list) 0750 { 0751 Node *n = list->tree; 0752 if (!n) { 0753 return; 0754 } 0755 0756 /* Check whether this is a when or an else statement */ 0757 if (n->kind == token_when) { 0758 list->tree = n->cond; 0759 visitStatements(list); 0760 list->tree = n->l; 0761 visitStatements(list); 0762 list->tree = n->r; 0763 visitWhenStatements(list); 0764 } else { 0765 list->tree = n->l; 0766 visitStatements(list); 0767 } 0768 list->tree = n; 0769 } 0770 0771 void AstVisitor::checkMethodCall(Ast *mc) 0772 { 0773 /* 0774 * The method call body resides in the left child. Check if this 0775 * is either a require, an include/extend or just a normal method call. 0776 * If the left child is nullptr, this is not a method call but a lambda 0777 * expression. 0778 */ 0779 if (mc->tree->l) { 0780 const QByteArray &name = QByteArray(mc->tree->l->name); 0781 if (name == "require") { 0782 (declaredInContext(name)) ? visitMethodCall(mc) : visitRequire(mc); 0783 } else if (name == "include") { 0784 (declaredInContext(name)) ? visitMethodCall(mc) : visitMixin(mc, true); 0785 } else if (name == "extend") { 0786 (declaredInContext(name)) ? visitMethodCall(mc) : visitMixin(mc, false); 0787 } else if (name == "require_relative") { 0788 (declaredInContext(name)) ? visitMethodCall(mc) : visitRequire(mc, true); 0789 } else if (name == "lambda") { 0790 (declaredInContext(name)) ? visitMethodCall(mc) : visitLambda(mc); 0791 } else { 0792 visitMethodCall(mc); 0793 } 0794 } else { 0795 visitLambda(mc); 0796 } 0797 } 0798