Commit 62141475 authored by Christian Kamm's avatar Christian Kamm
Browse files

QmlJS: Potentially fix hard-to-reproduce crash in JS completion.

* Context::build was potentially dangerous. Link and ScopeBuilder
  went out of scope before their results stopped being used.
* ScopeBuilder: If no function scope object was found, don't add it.

Reviewed-by: Erik Verbruggen
parent 56d0e4f3
......@@ -1395,13 +1395,6 @@ Context::~Context()
{
}
void Context::build(const QList<Node *> &astPath, QmlJS::Document::Ptr doc,
const QmlJS::Snapshot &snapshot, const QStringList &importPaths)
{
Link link(this, doc, snapshot, importPaths);
ScopeBuilder(doc, this).push(astPath);
}
Engine *Context::engine() const
{
return _engine;
......
......@@ -280,9 +280,6 @@ public:
Context(Engine *engine);
~Context();
void build(const QList<AST::Node *> &astPath, const Document::Ptr doc,
const Snapshot &snapshot, const QStringList &importPaths);
Engine *engine() const;
const ScopeChain &scopeChain() const;
ScopeChain &scopeChain();
......
......@@ -33,7 +33,8 @@ void ScopeBuilder::push(AST::Node *node)
// JS scopes
if (FunctionDeclaration *fun = cast<FunctionDeclaration *>(node)) {
ObjectValue *functionScope = _doc->bind()->findFunctionScope(fun);
_context->scopeChain().jsScopes += functionScope;
if (functionScope)
_context->scopeChain().jsScopes += functionScope;
}
_context->scopeChain().update();
......
......@@ -38,6 +38,7 @@
#include <qmljs/qmljsscanner.h>
#include <qmljs/qmljsevaluate.h>
#include <qmljs/qmljscompletioncontextfinder.h>
#include <qmljs/qmljslink.h>
#include <qmljs/qmljsscopebuilder.h>
#include <texteditor/basetexteditor.h>
......@@ -653,10 +654,11 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
Interpreter::Engine interp;
Interpreter::Context context(&interp);
Link link(&context, document, snapshot, m_modelManager->importPaths());
// Set up the current scope chain.
QList<AST::Node *> astPath = semanticInfo.astPath(editor->position());
context.build(astPath, document, snapshot, m_modelManager->importPaths());
ScopeBuilder scopeBuilder(document, &context);
scopeBuilder.push(semanticInfo.astPath(editor->position()));
// Search for the operator that triggered the completion.
QChar completionOperator;
......
......@@ -39,6 +39,8 @@
#include <qmljs/qmljscheck.h>
#include <qmljs/qmljsevaluate.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljslink.h>
#include <qmljs/qmljsscopebuilder.h>
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/parser/qmljsengine_p.h>
......@@ -1007,8 +1009,9 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
Interpreter::Engine interp;
Interpreter::Context context(&interp);
context.build(semanticInfo.astPath(cursorPosition), semanticInfo.document,
semanticInfo.snapshot, m_modelManager->importPaths());
QmlJS::Link linkedSnapshot(&context, semanticInfo.document, semanticInfo.snapshot, m_modelManager->importPaths());
ScopeBuilder scopeBuilder(semanticInfo.document, &context);
scopeBuilder.push(semanticInfo.astPath(cursorPosition));
Evaluate check(&context);
const Interpreter::Value *value = check.reference(node);
......@@ -1018,7 +1021,7 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
if (! (value && value->getSourceLocation(&fileName, &line, &column)))
return Link();
Link link;
BaseTextEditor::Link link;
link.fileName = fileName;
link.line = line;
link.column = column - 1; // adjust the column
......
......@@ -39,6 +39,8 @@
#include <qmljs/qmljsbind.h>
#include <qmljs/qmljsevaluate.h>
#include <qmljs/qmljsinterpreter.h>
#include <qmljs/qmljslink.h>
#include <qmljs/qmljsscopebuilder.h>
#include <qmljs/parser/qmljsast_p.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
......@@ -172,7 +174,9 @@ void HoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int p
Interpreter::Engine interp;
Interpreter::Context context(&interp);
context.build(astPath, qmlDocument, snapshot, m_modelManager->importPaths());
Link link(&context, qmlDocument, snapshot, m_modelManager->importPaths());
ScopeBuilder scopeBuilder(qmlDocument, &context);
scopeBuilder.push(astPath);
Evaluate check(&context);
const Interpreter::Value *value = check(node);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment