2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2011-04-15 16:19:23 +02:00
|
|
|
**
|
2014-01-07 13:27:11 +01:00
|
|
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
2012-10-02 09:12:39 +02:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
2011-04-15 16:19:23 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2011-04-15 16:19:23 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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.
|
2011-04-15 16:19:23 +02:00
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2011-04-15 16:19:23 +02:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2011-04-15 16:19:23 +02:00
|
|
|
|
|
|
|
|
#include "glslcompletionassist.h"
|
|
|
|
|
#include "glsleditorconstants.h"
|
|
|
|
|
#include "glsleditorplugin.h"
|
|
|
|
|
|
|
|
|
|
#include <glsl/glslengine.h>
|
|
|
|
|
#include <glsl/glsllexer.h>
|
|
|
|
|
#include <glsl/glslparser.h>
|
|
|
|
|
#include <glsl/glslsemantic.h>
|
|
|
|
|
#include <glsl/glslsymbols.h>
|
|
|
|
|
#include <glsl/glslastdump.h>
|
|
|
|
|
|
2012-02-14 16:43:51 +01:00
|
|
|
#include <coreplugin/idocument.h>
|
2011-04-15 16:19:23 +02:00
|
|
|
#include <texteditor/completionsettings.h>
|
2014-09-04 00:04:18 +02:00
|
|
|
#include <texteditor/codeassist/assistproposalitem.h>
|
|
|
|
|
#include <texteditor/codeassist/genericproposalmodel.h>
|
2011-04-15 16:19:23 +02:00
|
|
|
#include <texteditor/codeassist/genericproposal.h>
|
|
|
|
|
#include <texteditor/codeassist/functionhintproposal.h>
|
|
|
|
|
#include <cplusplus/ExpressionUnderCursor.h>
|
2014-02-17 19:23:20 +02:00
|
|
|
|
2011-04-15 16:19:23 +02:00
|
|
|
#include <utils/faketooltip.h>
|
2014-02-17 19:23:20 +02:00
|
|
|
#include <utils/qtcoverride.h>
|
2011-04-15 16:19:23 +02:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QIcon>
|
|
|
|
|
#include <QPainter>
|
|
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QToolButton>
|
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
#include <QApplication>
|
|
|
|
|
#include <QDesktopWidget>
|
|
|
|
|
#include <QDebug>
|
2011-04-15 16:19:23 +02:00
|
|
|
|
|
|
|
|
using namespace TextEditor;
|
|
|
|
|
|
2014-08-21 20:11:15 +02:00
|
|
|
namespace GlslEditor {
|
2014-08-21 08:29:55 +02:00
|
|
|
namespace Internal {
|
2011-04-15 16:19:23 +02:00
|
|
|
|
2014-08-22 17:16:02 +02:00
|
|
|
Document::Document()
|
|
|
|
|
: _engine(0)
|
|
|
|
|
, _ast(0)
|
|
|
|
|
, _globalScope(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Document::~Document()
|
|
|
|
|
{
|
|
|
|
|
delete _globalScope;
|
|
|
|
|
delete _engine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLSL::Scope *Document::scopeAt(int position) const
|
|
|
|
|
{
|
|
|
|
|
foreach (const Range &c, _cursors) {
|
|
|
|
|
if (position >= c.cursor.selectionStart() && position <= c.cursor.selectionEnd())
|
|
|
|
|
return c.scope;
|
|
|
|
|
}
|
|
|
|
|
return _globalScope;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Document::addRange(const QTextCursor &cursor, GLSL::Scope *scope)
|
|
|
|
|
{
|
|
|
|
|
Range c;
|
|
|
|
|
c.cursor = cursor;
|
|
|
|
|
c.scope = scope;
|
|
|
|
|
_cursors.append(c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-04-15 16:19:23 +02:00
|
|
|
enum CompletionOrder {
|
|
|
|
|
SpecialMemberOrder = -5
|
|
|
|
|
};
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
static bool isActivationChar(const QChar &ch)
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
return ch == QLatin1Char('(') || ch == QLatin1Char('.') || ch == QLatin1Char(',');
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
static bool isIdentifierChar(QChar ch)
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
return ch.isLetterOrNumber() || ch == QLatin1Char('_');
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
static bool isDelimiter(QChar ch)
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
switch (ch.unicode()) {
|
|
|
|
|
case '{':
|
|
|
|
|
case '}':
|
|
|
|
|
case '[':
|
|
|
|
|
case ']':
|
|
|
|
|
case ')':
|
|
|
|
|
case '?':
|
|
|
|
|
case '!':
|
|
|
|
|
case ':':
|
|
|
|
|
case ';':
|
|
|
|
|
case ',':
|
|
|
|
|
case '+':
|
|
|
|
|
case '-':
|
|
|
|
|
case '*':
|
|
|
|
|
case '/':
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
static bool checkStartOfIdentifier(const QString &word)
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
if (! word.isEmpty()) {
|
|
|
|
|
const QChar ch = word.at(0);
|
|
|
|
|
if (ch.isLetter() || ch == QLatin1Char('_'))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------
|
2014-08-21 08:29:55 +02:00
|
|
|
// GlslCompletionAssistProvider
|
2011-04-15 16:19:23 +02:00
|
|
|
// ----------------------------
|
2014-08-21 08:29:55 +02:00
|
|
|
bool GlslCompletionAssistProvider::supportsEditor(Core::Id editorId) const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
2012-08-03 15:24:33 +02:00
|
|
|
return editorId == Constants::C_GLSLEDITOR_ID;
|
2011-04-15 16:19:23 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
IAssistProcessor *GlslCompletionAssistProvider::createProcessor() const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
2014-08-21 08:29:55 +02:00
|
|
|
return new GlslCompletionAssistProcessor;
|
2011-04-15 16:19:23 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
int GlslCompletionAssistProvider::activationCharSequenceLength() const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
bool GlslCompletionAssistProvider::isActivationCharSequence(const QString &sequence) const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
return isActivationChar(sequence.at(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -----------------------------
|
2014-08-21 08:29:55 +02:00
|
|
|
// GlslFunctionHintProposalModel
|
2011-04-15 16:19:23 +02:00
|
|
|
// -----------------------------
|
2014-08-21 08:29:55 +02:00
|
|
|
class GlslFunctionHintProposalModel : public IFunctionHintProposalModel
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
public:
|
2014-08-21 08:29:55 +02:00
|
|
|
GlslFunctionHintProposalModel(QVector<GLSL::Function *> functionSymbols)
|
2011-04-15 16:19:23 +02:00
|
|
|
: m_items(functionSymbols)
|
|
|
|
|
, m_currentArg(-1)
|
|
|
|
|
{}
|
|
|
|
|
|
2014-02-17 19:23:20 +02:00
|
|
|
void reset() QTC_OVERRIDE {}
|
|
|
|
|
int size() const QTC_OVERRIDE { return m_items.size(); }
|
|
|
|
|
QString text(int index) const QTC_OVERRIDE;
|
|
|
|
|
int activeArgument(const QString &prefix) const QTC_OVERRIDE;
|
2011-04-15 16:19:23 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QVector<GLSL::Function *> m_items;
|
|
|
|
|
mutable int m_currentArg;
|
|
|
|
|
};
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
QString GlslFunctionHintProposalModel::text(int index) const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
return m_items.at(index)->prettyPrint(m_currentArg);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
int GlslFunctionHintProposalModel::activeArgument(const QString &prefix) const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
const QByteArray &str = prefix.toLatin1();
|
|
|
|
|
int argnr = 0;
|
|
|
|
|
int parcount = 0;
|
|
|
|
|
GLSL::Lexer lexer(0, str.constData(), str.length());
|
|
|
|
|
GLSL::Token tk;
|
|
|
|
|
QList<GLSL::Token> tokens;
|
|
|
|
|
do {
|
|
|
|
|
lexer.yylex(&tk);
|
|
|
|
|
tokens.append(tk);
|
|
|
|
|
} while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
|
|
|
|
|
for (int i = 0; i < tokens.count(); ++i) {
|
|
|
|
|
const GLSL::Token &tk = tokens.at(i);
|
|
|
|
|
if (tk.is(GLSL::Parser::T_LEFT_PAREN))
|
|
|
|
|
++parcount;
|
|
|
|
|
else if (tk.is(GLSL::Parser::T_RIGHT_PAREN))
|
|
|
|
|
--parcount;
|
|
|
|
|
else if (! parcount && tk.is(GLSL::Parser::T_COMMA))
|
|
|
|
|
++argnr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parcount < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (argnr != m_currentArg)
|
|
|
|
|
m_currentArg = argnr;
|
|
|
|
|
|
|
|
|
|
return argnr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -----------------------------
|
|
|
|
|
// GLSLCompletionAssistProcessor
|
|
|
|
|
// -----------------------------
|
2014-08-21 08:29:55 +02:00
|
|
|
GlslCompletionAssistProcessor::GlslCompletionAssistProcessor()
|
2011-04-15 16:19:23 +02:00
|
|
|
: m_startPosition(0)
|
2012-11-26 20:58:49 +02:00
|
|
|
, m_keywordIcon(QLatin1String(":/glsleditor/images/keyword.png"))
|
|
|
|
|
, m_varIcon(QLatin1String(":/glsleditor/images/var.png"))
|
|
|
|
|
, m_functionIcon(QLatin1String(":/glsleditor/images/func.png"))
|
|
|
|
|
, m_typeIcon(QLatin1String(":/glsleditor/images/type.png"))
|
|
|
|
|
, m_constIcon(QLatin1String(":/glsleditor/images/const.png"))
|
|
|
|
|
, m_attributeIcon(QLatin1String(":/glsleditor/images/attribute.png"))
|
|
|
|
|
, m_uniformIcon(QLatin1String(":/glsleditor/images/uniform.png"))
|
|
|
|
|
, m_varyingIcon(QLatin1String(":/glsleditor/images/varying.png"))
|
|
|
|
|
, m_otherIcon(QLatin1String(":/glsleditor/images/other.png"))
|
2011-04-15 16:19:23 +02:00
|
|
|
{}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
GlslCompletionAssistProcessor::~GlslCompletionAssistProcessor()
|
2011-04-15 16:19:23 +02:00
|
|
|
{}
|
|
|
|
|
|
2014-09-04 00:04:18 +02:00
|
|
|
IAssistProposal *GlslCompletionAssistProcessor::perform(const AssistInterface *interface)
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
2014-08-21 08:29:55 +02:00
|
|
|
m_interface.reset(static_cast<const GlslCompletionAssistInterface *>(interface));
|
2011-04-15 16:19:23 +02:00
|
|
|
|
|
|
|
|
if (interface->reason() == IdleEditor && !acceptsIdleEditor())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
int pos = m_interface->position() - 1;
|
|
|
|
|
QChar ch = m_interface->characterAt(pos);
|
|
|
|
|
while (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
|
|
|
|
|
ch = m_interface->characterAt(--pos);
|
|
|
|
|
|
|
|
|
|
CPlusPlus::ExpressionUnderCursor expressionUnderCursor;
|
|
|
|
|
//GLSLTextEditorWidget *edit = qobject_cast<GLSLTextEditorWidget *>(editor->widget());
|
|
|
|
|
|
|
|
|
|
QList<GLSL::Symbol *> members;
|
|
|
|
|
QStringList specialMembers;
|
|
|
|
|
|
|
|
|
|
bool functionCall = (ch == QLatin1Char('(') && pos == m_interface->position() - 1);
|
|
|
|
|
|
|
|
|
|
if (ch == QLatin1Char(',')) {
|
2012-02-14 16:43:51 +01:00
|
|
|
QTextCursor tc(m_interface->textDocument());
|
2011-04-15 16:19:23 +02:00
|
|
|
tc.setPosition(pos);
|
|
|
|
|
const int start = expressionUnderCursor.startOfFunctionCall(tc);
|
|
|
|
|
if (start == -1)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (m_interface->characterAt(start) == QLatin1Char('(')) {
|
|
|
|
|
pos = start;
|
|
|
|
|
ch = QLatin1Char('(');
|
|
|
|
|
functionCall = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ch == QLatin1Char('.') || functionCall) {
|
|
|
|
|
const bool memberCompletion = ! functionCall;
|
2012-02-14 16:43:51 +01:00
|
|
|
QTextCursor tc(m_interface->textDocument());
|
2011-04-15 16:19:23 +02:00
|
|
|
tc.setPosition(pos);
|
|
|
|
|
|
|
|
|
|
// get the expression under cursor
|
|
|
|
|
const QByteArray code = expressionUnderCursor(tc).toLatin1();
|
|
|
|
|
//qDebug() << endl << "expression:" << code;
|
|
|
|
|
|
|
|
|
|
// parse the expression
|
|
|
|
|
GLSL::Engine engine;
|
|
|
|
|
GLSL::Parser parser(&engine, code, code.size(), languageVariant(m_interface->mimeType()));
|
|
|
|
|
GLSL::ExpressionAST *expr = parser.parseExpression();
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
// dump it!
|
|
|
|
|
QTextStream qout(stdout, QIODevice::WriteOnly);
|
|
|
|
|
GLSL::ASTDump dump(qout);
|
|
|
|
|
dump(expr);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (Document::Ptr doc = m_interface->glslDocument()) {
|
|
|
|
|
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
|
|
|
|
|
|
|
|
|
GLSL::Semantic sem;
|
|
|
|
|
GLSL::Semantic::ExprResult exprTy = sem.expression(expr, currentScope, doc->engine());
|
|
|
|
|
if (exprTy.type) {
|
|
|
|
|
if (memberCompletion) {
|
|
|
|
|
if (const GLSL::VectorType *vecTy = exprTy.type->asVectorType()) {
|
|
|
|
|
members = vecTy->members();
|
|
|
|
|
|
|
|
|
|
// Sort the most relevant swizzle orderings to the top.
|
|
|
|
|
specialMembers += QLatin1String("xy");
|
|
|
|
|
specialMembers += QLatin1String("xyz");
|
|
|
|
|
specialMembers += QLatin1String("xyzw");
|
|
|
|
|
specialMembers += QLatin1String("rgb");
|
|
|
|
|
specialMembers += QLatin1String("rgba");
|
|
|
|
|
specialMembers += QLatin1String("st");
|
|
|
|
|
specialMembers += QLatin1String("stp");
|
|
|
|
|
specialMembers += QLatin1String("stpq");
|
|
|
|
|
|
|
|
|
|
} else if (const GLSL::Struct *structTy = exprTy.type->asStructType()) {
|
|
|
|
|
members = structTy->members();
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// some other type
|
|
|
|
|
}
|
|
|
|
|
} else { // function completion
|
|
|
|
|
QVector<GLSL::Function *> signatures;
|
|
|
|
|
if (const GLSL::Function *funTy = exprTy.type->asFunctionType())
|
|
|
|
|
signatures.append(const_cast<GLSL::Function *>(funTy)); // ### get rid of the const_cast
|
|
|
|
|
else if (const GLSL::OverloadSet *overload = exprTy.type->asOverloadSetType())
|
|
|
|
|
signatures = overload->functions();
|
|
|
|
|
|
|
|
|
|
if (! signatures.isEmpty()) {
|
|
|
|
|
m_startPosition = pos + 1;
|
|
|
|
|
return createHintProposal(signatures);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// undefined
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// sorry, there's no document
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// it's a global completion
|
|
|
|
|
if (Document::Ptr doc = m_interface->glslDocument()) {
|
|
|
|
|
GLSL::Scope *currentScope = doc->scopeAt(pos);
|
|
|
|
|
bool isGlobal = !currentScope || !currentScope->scope();
|
|
|
|
|
|
|
|
|
|
// add the members from the scope chain
|
|
|
|
|
for (; currentScope; currentScope = currentScope->scope())
|
|
|
|
|
members += currentScope->members();
|
|
|
|
|
|
|
|
|
|
// if this is the global scope, then add some standard Qt attribute
|
|
|
|
|
// and uniform names for autocompleting variable declarations
|
|
|
|
|
// this isn't a complete list, just the most common
|
|
|
|
|
if (isGlobal) {
|
|
|
|
|
static const char * const attributeNames[] = {
|
|
|
|
|
"qt_Vertex",
|
|
|
|
|
"qt_Normal",
|
|
|
|
|
"qt_MultiTexCoord0",
|
|
|
|
|
"qt_MultiTexCoord1",
|
|
|
|
|
"qt_MultiTexCoord2",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
static const char * const uniformNames[] = {
|
|
|
|
|
"qt_ModelViewProjectionMatrix",
|
|
|
|
|
"qt_ModelViewMatrix",
|
|
|
|
|
"qt_ProjectionMatrix",
|
|
|
|
|
"qt_NormalMatrix",
|
|
|
|
|
"qt_Texture0",
|
|
|
|
|
"qt_Texture1",
|
|
|
|
|
"qt_Texture2",
|
|
|
|
|
"qt_Color",
|
|
|
|
|
"qt_Opacity",
|
|
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
for (int index = 0; attributeNames[index]; ++index)
|
|
|
|
|
addCompletion(QString::fromLatin1(attributeNames[index]), m_attributeIcon);
|
|
|
|
|
for (int index = 0; uniformNames[index]; ++index)
|
|
|
|
|
addCompletion(QString::fromLatin1(uniformNames[index]), m_uniformIcon);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if (m_keywordVariant != languageVariant(m_interface->mimeType())) {
|
|
|
|
|
QStringList keywords = GLSL::Lexer::keywords(languageVariant(m_interface->mimeType()));
|
|
|
|
|
// m_keywordCompletions.clear();
|
|
|
|
|
for (int index = 0; index < keywords.size(); ++index)
|
|
|
|
|
addCompletion(keywords.at(index), m_keywordIcon);
|
|
|
|
|
// m_keywordVariant = languageVariant(m_interface->mimeType());
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// m_completions += m_keywordCompletions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (GLSL::Symbol *s, members) {
|
|
|
|
|
QIcon icon;
|
|
|
|
|
GLSL::Variable *var = s->asVariable();
|
|
|
|
|
if (var) {
|
|
|
|
|
int storageType = var->qualifiers() & GLSL::QualifiedTypeAST::StorageMask;
|
|
|
|
|
if (storageType == GLSL::QualifiedTypeAST::Attribute)
|
|
|
|
|
icon = m_attributeIcon;
|
|
|
|
|
else if (storageType == GLSL::QualifiedTypeAST::Uniform)
|
|
|
|
|
icon = m_uniformIcon;
|
|
|
|
|
else if (storageType == GLSL::QualifiedTypeAST::Varying)
|
|
|
|
|
icon = m_varyingIcon;
|
|
|
|
|
else if (storageType == GLSL::QualifiedTypeAST::Const)
|
|
|
|
|
icon = m_constIcon;
|
|
|
|
|
else
|
|
|
|
|
icon = m_varIcon;
|
|
|
|
|
} else if (s->asArgument()) {
|
|
|
|
|
icon = m_varIcon;
|
|
|
|
|
} else if (s->asFunction() || s->asOverloadSet()) {
|
|
|
|
|
icon = m_functionIcon;
|
|
|
|
|
} else if (s->asStruct()) {
|
|
|
|
|
icon = m_typeIcon;
|
|
|
|
|
} else {
|
|
|
|
|
icon = m_otherIcon;
|
|
|
|
|
}
|
|
|
|
|
if (specialMembers.contains(s->name()))
|
|
|
|
|
addCompletion(s->name(), icon, SpecialMemberOrder);
|
|
|
|
|
else
|
|
|
|
|
addCompletion(s->name(), icon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_startPosition = pos + 1;
|
|
|
|
|
return createContentProposal();
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
IAssistProposal *GlslCompletionAssistProcessor::createContentProposal() const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
2014-09-04 00:04:18 +02:00
|
|
|
GenericProposalModel *model = new GenericProposalModel(m_completions);
|
2011-04-15 16:19:23 +02:00
|
|
|
IAssistProposal *proposal = new GenericProposal(m_startPosition, model);
|
|
|
|
|
return proposal;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
IAssistProposal *GlslCompletionAssistProcessor::createHintProposal(
|
2011-04-15 16:19:23 +02:00
|
|
|
const QVector<GLSL::Function *> &symbols)
|
|
|
|
|
{
|
2014-08-21 08:29:55 +02:00
|
|
|
IFunctionHintProposalModel *model = new GlslFunctionHintProposalModel(symbols);
|
2011-04-15 16:19:23 +02:00
|
|
|
IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model);
|
|
|
|
|
return proposal;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
bool GlslCompletionAssistProcessor::acceptsIdleEditor() const
|
2011-04-15 16:19:23 +02:00
|
|
|
{
|
|
|
|
|
const int cursorPosition = m_interface->position();
|
|
|
|
|
const QChar ch = m_interface->characterAt(cursorPosition - 1);
|
|
|
|
|
|
|
|
|
|
const QChar characterUnderCursor = m_interface->characterAt(cursorPosition);
|
|
|
|
|
|
|
|
|
|
if (isIdentifierChar(ch) && (characterUnderCursor.isSpace() ||
|
|
|
|
|
characterUnderCursor.isNull() ||
|
|
|
|
|
isDelimiter(characterUnderCursor))) {
|
|
|
|
|
int pos = m_interface->position() - 1;
|
|
|
|
|
for (; pos != -1; --pos) {
|
|
|
|
|
if (! isIdentifierChar(m_interface->characterAt(pos)))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
const QString word = m_interface->textAt(pos, cursorPosition - pos);
|
|
|
|
|
if (word.length() > 2 && checkStartOfIdentifier(word)) {
|
|
|
|
|
for (int i = 0; i < word.length(); ++i) {
|
|
|
|
|
if (! isIdentifierChar(word.at(i)))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return isActivationChar(ch);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 08:29:55 +02:00
|
|
|
void GlslCompletionAssistProcessor::addCompletion(const QString &text,
|
2011-04-15 16:19:23 +02:00
|
|
|
const QIcon &icon,
|
|
|
|
|
int order)
|
|
|
|
|
{
|
2014-09-04 00:04:18 +02:00
|
|
|
AssistProposalItem *item = new AssistProposalItem;
|
2011-04-15 16:19:23 +02:00
|
|
|
item->setText(text);
|
|
|
|
|
item->setIcon(icon);
|
|
|
|
|
item->setOrder(order);
|
|
|
|
|
m_completions.append(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -----------------------------
|
2014-08-21 08:29:55 +02:00
|
|
|
// GlslCompletionAssistInterface
|
2011-04-15 16:19:23 +02:00
|
|
|
// -----------------------------
|
2014-08-21 08:29:55 +02:00
|
|
|
GlslCompletionAssistInterface::GlslCompletionAssistInterface(QTextDocument *textDocument,
|
2011-04-15 16:19:23 +02:00
|
|
|
int position,
|
2013-03-18 14:58:46 +01:00
|
|
|
const QString &fileName,
|
2014-08-21 08:29:55 +02:00
|
|
|
AssistReason reason,
|
2011-04-15 16:19:23 +02:00
|
|
|
const QString &mimeType,
|
|
|
|
|
const Document::Ptr &glslDoc)
|
2014-09-04 00:04:18 +02:00
|
|
|
: AssistInterface(textDocument, position, fileName, reason)
|
2011-04-15 16:19:23 +02:00
|
|
|
, m_mimeType(mimeType)
|
|
|
|
|
, m_glslDoc(glslDoc)
|
|
|
|
|
{
|
|
|
|
|
}
|
2014-08-21 08:29:55 +02:00
|
|
|
|
|
|
|
|
} // namespace Internal
|
2014-08-21 20:11:15 +02:00
|
|
|
} // namespace GlslEditor
|