TypeOfExpression.cpp 6.56 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
hjk's avatar
hjk committed
3 4
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
con's avatar
con committed
29 30

#include "TypeOfExpression.h"
31
#include <TranslationUnit.h>
32
#include "LookupContext.h"
33 34
#include "ResolveExpression.h"
#include "pp.h"
con's avatar
con committed
35 36

#include <AST.h>
37
#include <Symbol.h>
Roberto Raggi's avatar
Roberto Raggi committed
38
#include <QSet>
con's avatar
con committed
39 40 41 42

using namespace CPlusPlus;

TypeOfExpression::TypeOfExpression():
43
    m_ast(0),
44 45
    m_scope(0),
    m_expandTemplates(false)
con's avatar
con committed
46 47 48
{
}

49
void TypeOfExpression::reset()
50
{
51 52 53
    m_thisDocument.clear();
    m_snapshot = Snapshot();
    m_ast = 0;
54
    m_scope = 0;
55 56 57
    m_lookupContext = LookupContext();
    m_bindings.clear();
    m_environment.clear();
58 59
}

60 61
void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot,
                            QSharedPointer<CreateBindings> bindings)
con's avatar
con committed
62
{
63 64 65
    m_thisDocument = thisDocument;
    m_snapshot = snapshot;
    m_ast = 0;
66
    m_scope = 0;
67 68 69
    m_lookupContext = LookupContext();
    m_bindings = bindings;
    m_environment.clear();
con's avatar
con committed
70 71
}

72
QList<LookupItem> TypeOfExpression::operator()(const QByteArray &utf8code,
73
                                               Scope *scope,
74
                                               PreprocessMode mode)
con's avatar
con committed
75
{
76
    Document::Ptr expressionDoc;
77
    if (mode == Preprocess)
78 79 80
        expressionDoc = documentForExpression(preprocessedExpression(utf8code));
    else
        expressionDoc = documentForExpression(utf8code);
81
    expressionDoc->check();
82 83 84 85 86
    return this->operator ()(extractExpressionAST(expressionDoc),
                             expressionDoc,
                             scope);
}

87 88

QList<LookupItem> TypeOfExpression::reference(const QByteArray &utf8code,
89 90 91
                                              Scope *scope,
                                              PreprocessMode mode)
{
92
    Document::Ptr expressionDoc;
93
    if (mode == Preprocess)
94 95 96
        expressionDoc = documentForExpression(preprocessedExpression(utf8code));
    else
        expressionDoc = documentForExpression(utf8code);
97 98 99 100
    expressionDoc->check();
    return reference(extractExpressionAST(expressionDoc), expressionDoc, scope);
}

101 102 103 104 105
QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
                                               Document::Ptr document,
                                               Scope *scope)
{
    m_ast = expression;
con's avatar
con committed
106

107
    m_scope = scope;
108

109
    m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot);
110
    m_lookupContext.setBindings(m_bindings);
111
    m_lookupContext.setExpandTemplates(m_expandTemplates);
con's avatar
con committed
112

113
    ResolveExpression resolve(m_lookupContext);
Roberto Raggi's avatar
Roberto Raggi committed
114 115 116 117 118 119
    const QList<LookupItem> items = resolve(m_ast, scope);

    if (! m_bindings)
        m_lookupContext = resolve.context();

    return items;
con's avatar
con committed
120 121
}

122 123 124 125 126 127 128 129 130 131
QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
                                              Document::Ptr document,
                                              Scope *scope)
{
    m_ast = expression;

    m_scope = scope;

    m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot);
    m_lookupContext.setBindings(m_bindings);
132
    m_lookupContext.setExpandTemplates(m_expandTemplates);
133 134 135 136 137 138 139 140 141 142

    ResolveExpression resolve(m_lookupContext);
    const QList<LookupItem> items = resolve.reference(m_ast, scope);

    if (! m_bindings)
        m_lookupContext = resolve.context();

    return items;
}

143
QByteArray TypeOfExpression::preprocess(const QByteArray &utf8code) const
144
{
145
    return preprocessedExpression(utf8code);
146 147
}

con's avatar
con committed
148 149 150 151 152
ExpressionAST *TypeOfExpression::ast() const
{
    return m_ast;
}

153
Scope *TypeOfExpression::scope() const
154
{
155
    return m_scope;
156 157
}

158
const LookupContext &TypeOfExpression::context() const
con's avatar
con committed
159 160 161 162 163 164 165 166 167
{
    return m_lookupContext;
}

ExpressionAST *TypeOfExpression::expressionAST() const
{
    return extractExpressionAST(m_lookupContext.expressionDocument());
}

168
void TypeOfExpression::processEnvironment(Document::Ptr doc, Environment *env,
169 170
                                          QSet<QString> *processed) const
{
171 172 173 174 175 176 177 178
    if (doc && ! processed->contains(doc->fileName())) {
        processed->insert(doc->fileName());

        foreach (const Document::Include &incl, doc->includes())
            processEnvironment(m_snapshot.document(incl.fileName()), env, processed);

        foreach (const Macro &macro, doc->definedMacros())
            env->bind(macro);
179 180 181
    }
}

182
QByteArray TypeOfExpression::preprocessedExpression(const QByteArray &utf8code) const
183
{
184 185
    if (utf8code.trimmed().isEmpty())
        return utf8code;
186

187 188 189 190 191 192 193 194 195
    if (! m_environment) {
        Environment *env = new Environment(); // ### cache the environment.

        QSet<QString> processed;
        processEnvironment(m_thisDocument, env, &processed);
        m_environment = QSharedPointer<Environment>(env);
    }

    Preprocessor preproc(0, m_environment.data());
196
    return preproc.run("<expression>", utf8code);
197
}
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

namespace CPlusPlus {

ExpressionAST *extractExpressionAST(Document::Ptr doc)
{
    if (! doc->translationUnit()->ast())
        return 0;

    return doc->translationUnit()->ast()->asExpression();
}

Document::Ptr documentForExpression(const QByteArray &utf8code)
{
    // create the expression's AST.
    Document::Ptr doc = Document::create(QLatin1String("<completion>"));
    doc->setUtf8Source(utf8code);
    doc->parse(Document::ParseExpression);
    return doc;
}

} // namespace CPlusPlus