/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "qtscripteditor.h" #include "qtscripteditorconstants.h" #include "qtscripthighlighter.h" #include "qtscripteditorplugin.h" #include "qtscriptindenter.h" #include "parser/javascriptengine_p.h" #include "parser/javascriptparser_p.h" #include "parser/javascriptlexer_p.h" #include "parser/javascriptnodepool_p.h" #include "parser/javascriptastvisitor_p.h" #include "parser/javascriptast_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum { UPDATE_DOCUMENT_DEFAULT_INTERVAL = 100 }; using namespace JavaScript::AST; namespace QtScriptEditor { namespace Internal { class FindDeclarations: protected Visitor { QList declarations; public: QList accept(JavaScript::AST::Node *node) { JavaScript::AST::Node::acceptChild(node, this); return declarations; } protected: using Visitor::visit; virtual bool visit(FunctionExpression *) { return false; } virtual bool visit(FunctionDeclaration *ast) { if (! ast->name) return false; QString text = ast->name->asString(); text += QLatin1Char('('); for (FormalParameterList *it = ast->formals; it; it = it->next) { if (it->name) text += it->name->asString(); if (it->next) text += QLatin1String(", "); } text += QLatin1Char(')'); Declaration d; d.text = text; d.startLine = ast->startLine; d.startColumn = ast->startColumn; d.endLine = ast->endLine; d.endColumn = ast->endColumn; declarations.append(d); return false; } virtual bool visit(VariableDeclaration *ast) { if (! ast->name) return false; Declaration d; d.text = ast->name->asString(); d.startLine= ast->startLine; d.startColumn = ast->startColumn; d.endLine = ast->endLine; d.endColumn = ast->endColumn; declarations.append(d); return false; } }; ScriptEditorEditable::ScriptEditorEditable(ScriptEditor *editor, const QList& context) : BaseTextEditorEditable(editor), m_context(context) { } ScriptEditor::ScriptEditor(const Context &context, QWidget *parent) : TextEditor::BaseTextEditor(parent), m_context(context), m_methodCombo(0) { setParenthesesMatchingEnabled(true); setMarksVisible(true); setCodeFoldingSupported(true); setCodeFoldingVisible(true); setMimeType(QtScriptEditor::Constants::C_QTSCRIPTEDITOR_MIMETYPE); m_updateDocumentTimer = new QTimer(this); m_updateDocumentTimer->setInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL); m_updateDocumentTimer->setSingleShot(true); connect(m_updateDocumentTimer, SIGNAL(timeout()), this, SLOT(updateDocumentNow())); connect(this, SIGNAL(textChanged()), this, SLOT(updateDocument())); baseTextDocument()->setSyntaxHighlighter(new QtScriptHighlighter); } ScriptEditor::~ScriptEditor() { } QList ScriptEditor::declarations() const { return m_declarations; } QStringList ScriptEditor::words() const { return m_words; } Core::IEditor *ScriptEditorEditable::duplicate(QWidget *parent) { ScriptEditor *newEditor = new ScriptEditor(m_context, parent); newEditor->duplicateFrom(editor()); QtScriptEditorPlugin::instance()->initializeEditor(newEditor); return newEditor->editableInterface(); } const char *ScriptEditorEditable::kind() const { return QtScriptEditor::Constants::C_QTSCRIPTEDITOR; } ScriptEditor::Context ScriptEditorEditable::context() const { return m_context; } void ScriptEditor::updateDocument() { m_updateDocumentTimer->start(UPDATE_DOCUMENT_DEFAULT_INTERVAL); } void ScriptEditor::updateDocumentNow() { // ### move in the parser thread. m_updateDocumentTimer->stop(); const QString fileName = file()->fileName(); const QString code = toPlainText(); JavaScriptParser parser; JavaScriptEnginePrivate driver; JavaScript::NodePool nodePool(fileName, &driver); driver.setNodePool(&nodePool); JavaScript::Lexer lexer(&driver); lexer.setCode(code, /*line = */ 1); driver.setLexer(&lexer); if (parser.parse(&driver)) { JavaScript::AST::Visitor v; driver.ast()->accept(&v); FindDeclarations decls; m_declarations = decls.accept(driver.ast()); m_words.clear(); foreach (const JavaScriptNameIdImpl &id, driver.literals()) m_words.append(id.asString()); QStringList items; items.append(tr("