File indexing completed on 2024-04-14 04:31:15

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/parser.h>
0020 
0021 #include <language/editor/documentrange.h>
0022 
0023 using namespace KDevelop;
0024 
0025 namespace ruby
0026 {
0027 
0028 Parser::Parser()
0029 {
0030     m_contents = nullptr;
0031     m_version = ruby21;
0032     ast = nullptr;
0033 }
0034 
0035 Parser::Parser(const IndexedString &fileName, const QByteArray &contents)
0036 {
0037     currentDocument = fileName;
0038     m_contents = contents;
0039     m_version = ruby21;
0040     ast = nullptr;
0041 }
0042 
0043 Parser::~Parser()
0044 {
0045     if (ast) {
0046         free_ast(ast->tree);
0047         delete ast;
0048         ast = nullptr;
0049     }
0050 }
0051 
0052 void Parser::setContents(const QByteArray &contents)
0053 {
0054     m_contents = contents;
0055 }
0056 
0057 void Parser::setRubyVersion(enum ruby_version version)
0058 {
0059     m_version = version;
0060 }
0061 
0062 Ast * Parser::parse()
0063 {
0064     struct options_t opts;
0065     struct error_t *aux;
0066     opts.path = currentDocument.str().toUtf8();
0067     opts.contents = m_contents.data();
0068     opts.version = m_version;
0069 
0070     // Let's call the parser ;)
0071     struct ast_t *res = rb_compile_file(&opts);
0072     ast = new Ast(res->tree);
0073     if (res->unrecoverable) {
0074         for (aux = res->errors; aux; aux = aux->next) {
0075             appendProblem(aux);
0076         }
0077         delete ast;
0078         ast = nullptr;
0079         rb_free(res);
0080         return nullptr;
0081     } else {
0082         problems.clear();
0083         for (aux = res->errors; aux; aux = aux->next) {
0084             appendProblem(aux);
0085         }
0086         free_errors(res);
0087         free(res);
0088     }
0089     return ast;
0090 }
0091 
0092 void Parser::mapAstUse(Ast *node, const SimpleUse &use)
0093 {
0094     Q_UNUSED(node);
0095     Q_UNUSED(use);
0096 }
0097 
0098 const QString Parser::symbol(const Node *node) const
0099 {
0100     int len = node->pos.end_col - node->pos.start_col;
0101     return m_contents.mid(node->pos.offset - len, len);
0102 }
0103 
0104 void Parser::appendProblem(const struct error_t *error)
0105 {
0106     int col = (error->column > 0) ? error->column - 1 : 0;
0107     ProblemPointer problem(new KDevelop::Problem);
0108 
0109     KTextEditor::Cursor cursor(error->line - 1, col);
0110     KTextEditor::Range range(cursor, cursor);
0111     DocumentRange location(currentDocument, range);
0112     problem->setFinalLocation(location);
0113     problem->setDescription(QString(error->msg));
0114     problem->setSource(IProblem::Parser);
0115     if (error->warning) {
0116         problem->setSeverity(IProblem::Error);
0117     } else {
0118         problem->setSeverity(IProblem::Warning);
0119     }
0120     problems << problem;
0121 }
0122 
0123 }
0124