Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Q
qt-creator
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Tobias Hunger
qt-creator
Commits
ba3e68fc
Commit
ba3e68fc
authored
15 years ago
by
Roberto Raggi
Browse files
Options
Downloads
Patches
Plain Diff
Try to get the type of the qualified name id under cursor
parent
4b97bf17
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/libs/qmljs/qmljsdocument.cpp
+34
-16
34 additions, 16 deletions
src/libs/qmljs/qmljsdocument.cpp
src/libs/qmljs/qmljsdocument.h
+2
-2
2 additions, 2 deletions
src/libs/qmljs/qmljsdocument.h
src/plugins/qmljseditor/qmlcodecompletion.cpp
+99
-57
99 additions, 57 deletions
src/plugins/qmljseditor/qmlcodecompletion.cpp
with
135 additions
and
75 deletions
src/libs/qmljs/qmljsdocument.cpp
+
34
−
16
View file @
ba3e68fc
...
...
@@ -42,8 +42,7 @@ using namespace QmlJS::AST;
Document
::
Document
(
const
QString
&
fileName
)
:
_engine
(
0
)
,
_pool
(
0
)
,
_uiProgram
(
0
)
,
_jsProgram
(
0
)
,
_ast
(
0
)
,
_fileName
(
fileName
)
,
_parsedCorrectly
(
false
)
{
...
...
@@ -74,20 +73,17 @@ Document::Ptr Document::create(const QString &fileName)
AST
::
UiProgram
*
Document
::
qmlProgram
()
const
{
return
_u
iProgram
;
return
cast
<
U
iProgram
*>
(
_ast
)
;
}
AST
::
Program
*
Document
::
jsProgram
()
const
{
return
_js
Program
;
return
cast
<
Program
*>
(
_ast
)
;
}
AST
::
Node
*
Document
::
ast
()
const
{
Q_ASSERT
(
!
_uiProgram
||
!
_jsProgram
);
if
(
_uiProgram
)
return
_uiProgram
;
return
_jsProgram
;
return
_ast
;
}
QList
<
DiagnosticMessage
>
Document
::
diagnosticMessages
()
const
...
...
@@ -109,8 +105,7 @@ bool Document::parseQml()
{
Q_ASSERT
(
!
_engine
);
Q_ASSERT
(
!
_pool
);
Q_ASSERT
(
!
_uiProgram
);
Q_ASSERT
(
!
_jsProgram
);
Q_ASSERT
(
!
_ast
);
_engine
=
new
Engine
();
_pool
=
new
NodePool
(
_fileName
,
_engine
);
...
...
@@ -122,11 +117,11 @@ bool Document::parseQml()
lexer
.
setCode
(
_source
,
/*line = */
1
);
_parsedCorrectly
=
parser
.
parse
();
_
uiProgram
=
parser
.
ast
();
_
ast
=
parser
.
ast
();
_diagnosticMessages
=
parser
.
diagnosticMessages
();
if
(
_ui
Program
)
{
for
(
QmlJS
::
AST
::
UiObjectMemberList
*
iter
=
_ui
Program
->
members
;
iter
;
iter
=
iter
->
next
)
if
(
qml
Program
()
)
{
for
(
QmlJS
::
AST
::
UiObjectMemberList
*
iter
=
qml
Program
()
->
members
;
iter
;
iter
=
iter
->
next
)
if
(
iter
->
member
)
_symbols
.
append
(
new
SymbolFromFile
(
_fileName
,
iter
->
member
));
...
...
@@ -143,8 +138,7 @@ bool Document::parseJavaScript()
{
Q_ASSERT
(
!
_engine
);
Q_ASSERT
(
!
_pool
);
Q_ASSERT
(
!
_uiProgram
);
Q_ASSERT
(
!
_jsProgram
);
Q_ASSERT
(
!
_ast
);
_engine
=
new
Engine
();
_pool
=
new
NodePool
(
_fileName
,
_engine
);
...
...
@@ -156,7 +150,31 @@ bool Document::parseJavaScript()
lexer
.
setCode
(
_source
,
/*line = */
1
);
_parsedCorrectly
=
parser
.
parseProgram
();
_jsProgram
=
cast
<
Program
*>
(
parser
.
rootNode
());
_ast
=
cast
<
Program
*>
(
parser
.
rootNode
());
_diagnosticMessages
=
parser
.
diagnosticMessages
();
return
_parsedCorrectly
;
}
bool
Document
::
parseExpression
()
{
Q_ASSERT
(
!
_engine
);
Q_ASSERT
(
!
_pool
);
Q_ASSERT
(
!
_ast
);
_engine
=
new
Engine
();
_pool
=
new
NodePool
(
_fileName
,
_engine
);
_ids
.
clear
();
Lexer
lexer
(
_engine
);
Parser
parser
(
_engine
);
lexer
.
setCode
(
_source
,
/*line = */
1
);
_parsedCorrectly
=
parser
.
parseExpression
();
_ast
=
parser
.
rootNode
();
if
(
_ast
)
_ast
=
_ast
->
expressionCast
();
_diagnosticMessages
=
parser
.
diagnosticMessages
();
return
_parsedCorrectly
;
...
...
This diff is collapsed.
Click to expand it.
src/libs/qmljs/qmljsdocument.h
+
2
−
2
View file @
ba3e68fc
...
...
@@ -67,6 +67,7 @@ public:
bool
parseQml
();
bool
parseJavaScript
();
bool
parseExpression
();
bool
isParsedCorrectly
()
const
{
return
_parsedCorrectly
;
}
...
...
@@ -84,8 +85,7 @@ public:
private
:
QmlJS
::
Engine
*
_engine
;
QmlJS
::
NodePool
*
_pool
;
QmlJS
::
AST
::
UiProgram
*
_uiProgram
;
QmlJS
::
AST
::
Program
*
_jsProgram
;
QmlJS
::
AST
::
Node
*
_ast
;
QList
<
QmlJS
::
DiagnosticMessage
>
_diagnosticMessages
;
QString
_fileName
;
QString
_path
;
...
...
This diff is collapsed.
Click to expand it.
src/plugins/qmljseditor/qmlcodecompletion.cpp
+
99
−
57
View file @
ba3e68fc
...
...
@@ -50,6 +50,7 @@
using
namespace
QmlJSEditor
;
using
namespace
QmlJSEditor
::
Internal
;
using
namespace
QmlJS
;
// Temporary workaround until we have proper icons for QML completion items
...
...
@@ -83,6 +84,7 @@ static QIcon iconForColor(const QColor &color)
return
pix
;
}
namespace
{
class
Evaluate
:
public
QmlJS
::
AST
::
Visitor
{
...
...
@@ -181,6 +183,46 @@ protected:
};
class
EnumerateProperties
{
QSet
<
const
Interpreter
::
ObjectValue
*>
_processed
;
QHash
<
QString
,
const
Interpreter
::
Value
*>
_properties
;
public:
QHash
<
QString
,
const
Interpreter
::
Value
*>
operator
()(
const
Interpreter
::
Value
*
value
)
{
_processed
.
clear
();
_properties
.
clear
();
enumerateProperties
(
value
);
return
_properties
;
}
private
:
void
enumerateProperties
(
const
Interpreter
::
Value
*
value
)
{
if
(
!
value
)
return
;
else
if
(
const
Interpreter
::
ObjectValue
*
object
=
value
->
asObjectValue
())
{
enumerateProperties
(
object
);
}
}
void
enumerateProperties
(
const
Interpreter
::
ObjectValue
*
object
)
{
if
(
!
object
||
_processed
.
contains
(
object
))
return
;
_processed
.
insert
(
object
);
enumerateProperties
(
object
->
prototype
());
for
(
Interpreter
::
ObjectValue
::
MemberIterator
it
=
object
->
firstMember
();
it
!=
object
->
lastMember
();
++
it
)
{
_properties
.
insert
(
it
.
key
(),
it
.
value
());
}
}
};
}
// end of anonymous namespace
QmlCodeCompletion
::
QmlCodeCompletion
(
QmlModelManagerInterface
*
modelManager
,
QmlJS
::
TypeSystem
*
typeSystem
,
QObject
*
parent
)
:
TextEditor
::
ICompletionCollector
(
parent
),
m_modelManager
(
modelManager
),
...
...
@@ -248,32 +290,33 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
const
QIcon
typeIcon
=
iconForColor
(
Qt
::
yellow
);
foreach
(
QmlJS
::
Document
::
Ptr
doc
,
snapshot
)
{
const
QFileInfo
fileInfo
(
doc
->
fileName
());
if
(
fileInfo
.
suffix
()
!=
QLatin1String
(
"qml"
))
continue
;
else
if
(
fileInfo
.
absolutePath
()
!=
currentFilePath
)
// ### FIXME includ `imported' components
continue
;
const
QString
typeName
=
fileInfo
.
baseName
();
if
(
typeName
.
isEmpty
())
continue
;
if
(
typeName
.
at
(
0
).
isUpper
())
{
TextEditor
::
CompletionItem
item
(
this
);
item
.
text
=
typeName
;
item
.
icon
=
typeIcon
;
m_completions
.
append
(
item
);
}
}
QChar
previousChar
;
if
(
m_startPosition
>
0
)
previousChar
=
editor
->
characterAt
(
m_startPosition
-
1
);
if
(
previousChar
.
isSpace
()
||
previousChar
.
isNull
())
{
// ### FIXME
// Add the visible components to the completion box.
foreach
(
QmlJS
::
Document
::
Ptr
doc
,
snapshot
)
{
const
QFileInfo
fileInfo
(
doc
->
fileName
());
if
(
fileInfo
.
suffix
()
!=
QLatin1String
(
"qml"
))
continue
;
else
if
(
fileInfo
.
absolutePath
()
!=
currentFilePath
)
// ### FIXME includ `imported' components
continue
;
const
QString
typeName
=
fileInfo
.
baseName
();
if
(
typeName
.
isEmpty
())
continue
;
if
(
typeName
.
at
(
0
).
isUpper
())
{
TextEditor
::
CompletionItem
item
(
this
);
item
.
text
=
typeName
;
item
.
icon
=
typeIcon
;
m_completions
.
append
(
item
);
}
}
// Add the visible IDs to the completion box
const
QIcon
idIcon
=
iconForColor
(
Qt
::
darkGray
);
QStringList
ids
=
qmlDocument
->
ids
().
keys
();
foreach
(
const
QString
&
id
,
ids
)
{
...
...
@@ -287,54 +330,53 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
}
}
#if 0
// FIXME: this completion strategy is not going to work when the document was never parsed correctly.
if (qmlDocument->qmlProgram() != 0) {
const QIcon otherIcon = iconForColor(Qt::darkCyan);
if
(
previousChar
==
QLatin1Char
(
'.'
))
{
const
int
endOfExpression
=
m_startPosition
-
1
;
int
startOfExpression
=
endOfExpression
-
2
;
// qDebug() << "*** program:" << program;
QmlExpressionUnderCursor expressionUnderCursor;
QTextCursor cursor(edit->document());
cursor.setPosition(pos);
expressionUnderCursor(cursor, qmlDocument);
while
(
startOfExpression
>=
0
)
{
const
QChar
ch
=
editor
->
characterAt
(
startOfExpression
);
QmlLookupContext context(expressionUnderCursor.expressionScopes(), qmlDocument, m_modelManager->snapshot(), m_typeSystem);
QmlResolveExpression resolver(context);
if
(
ch
.
isLetterOrNumber
()
||
ch
==
QLatin1Char
(
'_'
)
||
ch
==
QLatin1Char
(
'.'
))
--
startOfExpression
;
else
break
;
}
++
startOfExpression
;
QmlJS::AST::Node *expr = expressionUnderCursor.expressionNode();
const
QString
expression
=
m_editor
->
textAt
(
startOfExpression
,
endOfExpression
-
startOfExpression
);
//qDebug() << "expression:" << expression;
QmlJS::Interpreter::Engine engine;
Evaluate evaluate(&engine);
if (const QmlJS::Interpreter::Value *value = evaluate(expr)) {
if (const QmlJS::Interpreter::ObjectValue *object = value->asObjectValue()) {
for (QmlJS::Interpreter::ObjectValue::MemberIterator it = object->firstMember(); it != object->lastMember(); ++it) {
TextEditor::CompletionItem item(this);
item.text = it.key();
item.icon = otherIcon;
m_completions.append(item);
}
return pos;
}
}
QmlJS
::
Document
::
Ptr
exprDoc
=
QmlJS
::
Document
::
create
(
QLatin1String
(
"<expression>"
));
exprDoc
->
setSource
(
expression
);
exprDoc
->
parseExpression
();
if
(
exprDoc
->
ast
())
{
Interpreter
::
Engine
interp
;
Evaluate
evaluate
(
&
interp
);
const
Interpreter
::
Value
*
value
=
interp
.
convertToObject
(
evaluate
(
exprDoc
->
ast
()));
//qDebug() << "type:" << interp.typeId(value);
// qDebug()<<"*** expression under cursor:"<<expressionUnderCursor.expressionNode();
const QList<QmlJS::Symbol*> symbols = resolver.visibleSymbols(expressionUnderCursor.expressionNode());
// qDebug()<<"***"<<symbols.size()<<"visible symbols";
const
QIcon
symbolIcon
=
iconForColor
(
Qt
::
darkCyan
);
foreach (QmlJS::Symbol *symbol, symbols) {
if (symbol->isIdSymbol())
continue; // nothing to do here.
EnumerateProperties
enumerateProperties
;
QHashIterator
<
QString
,
const
Interpreter
::
Value
*>
it
(
enumerateProperties
(
value
));
while
(
it
.
hasNext
())
{
it
.
next
();
const QString word = symbol->name();
if (! word.isEmpty()) {
TextEditor
::
CompletionItem
item
(
this
);
item.text =
word
;
item.icon =
other
Icon;
item
.
text
=
it
.
key
()
;
item
.
icon
=
symbol
Icon
;
m_completions
.
append
(
item
);
}
}
if
(
!
m_completions
.
isEmpty
())
return
m_startPosition
;
return
-
1
;
}
#endif
if
(
previousChar
.
isNull
()
||
previousChar
.
isSpace
()
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment