Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
e9039db9
Commit
e9039db9
authored
Feb 19, 2010
by
Christian Kamm
Browse files
Move the scope building logic into QmlJS::ScopeBuilder.
parent
08cfc8f2
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/libs/qmljs/qmljs-lib.pri
View file @
e9039db9
...
...
@@ -17,7 +17,8 @@ HEADERS += \
$$PWD/qmljsscanner.h \
$$PWD/qmljsinterpreter.h \
$$PWD/qmljslink.h \
$$PWD/qmljscheck.h
$$PWD/qmljscheck.h \
$$PWD/qmljsscopebuilder.h
SOURCES += \
$$PWD/qmljsbind.cpp \
...
...
@@ -27,7 +28,8 @@ SOURCES += \
$$PWD/qmljsinterpreter.cpp \
$$PWD/qmljsmetatypesystem.cpp \
$$PWD/qmljslink.cpp \
$$PWD/qmljscheck.cpp
$$PWD/qmljscheck.cpp \
$$PWD/qmljsscopebuilder.cpp
contains(QT_CONFIG, declarative) {
QT += declarative
...
...
src/libs/qmljs/qmljscheck.cpp
View file @
e9039db9
...
...
@@ -61,7 +61,7 @@ Check::Check(Document::Ptr doc, const Snapshot &snapshot)
,
_snapshot
(
snapshot
)
,
_context
(
&
_engine
)
,
_link
(
&
_context
,
doc
,
snapshot
)
,
_
allowAnyProperty
(
false
)
,
_
scopeBuilder
(
doc
,
&
_context
)
{
}
...
...
@@ -109,71 +109,20 @@ void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
return
;
}
const
bool
oldAllowAnyProperty
=
_allowAnyProperty
;
_scopeBuilder
.
push
(
ast
)
;
if
(
!
_context
.
lookupType
(
_doc
.
data
(),
typeId
))
{
warning
(
typeId
->
identifierToken
,
tr
(
Messages
::
unknown_type
));
_allowAnyProperty
=
true
;
// suppress subsequent "unknown property" errors
// suppress subsequent errors about scope object lookup by clearing
// the scope object list
// ### todo: better way?
_context
.
scopeChain
().
qmlScopeObjects
.
clear
();
_context
.
scopeChain
().
update
();
}
QList
<
const
ObjectValue
*>
oldScopeObjects
=
_context
.
scopeChain
().
qmlScopeObjects
;
_context
.
scopeChain
().
qmlScopeObjects
.
clear
();
const
ObjectValue
*
scopeObject
=
_doc
->
bind
()
->
findQmlObject
(
ast
);
_context
.
scopeChain
().
qmlScopeObjects
+=
scopeObject
;
_context
.
scopeChain
().
update
();
#ifndef NO_DECLARATIVE_BACKEND
// check if the object has a Qt.ListElement ancestor
const
ObjectValue
*
prototype
=
scopeObject
->
prototype
(
&
_context
);
while
(
prototype
)
{
if
(
const
QmlObjectValue
*
qmlMetaObject
=
dynamic_cast
<
const
QmlObjectValue
*>
(
prototype
))
{
// ### Also check for Qt package. Involves changes in QmlObjectValue.
if
(
qmlMetaObject
->
qmlTypeName
()
==
QLatin1String
(
"ListElement"
))
{
_allowAnyProperty
=
true
;
break
;
}
}
prototype
=
prototype
->
prototype
(
&
_context
);
}
// check if the object has a Qt.PropertyChanges ancestor
prototype
=
scopeObject
->
prototype
(
&
_context
);
while
(
prototype
)
{
if
(
const
QmlObjectValue
*
qmlMetaObject
=
dynamic_cast
<
const
QmlObjectValue
*>
(
prototype
))
{
// ### Also check for Qt package. Involves changes in QmlObjectValue.
if
(
qmlMetaObject
->
qmlTypeName
()
==
QLatin1String
(
"PropertyChanges"
))
break
;
}
prototype
=
prototype
->
prototype
(
&
_context
);
}
// find the target script binding
if
(
prototype
&&
initializer
)
{
for
(
UiObjectMemberList
*
m
=
initializer
->
members
;
m
;
m
=
m
->
next
)
{
if
(
UiScriptBinding
*
scriptBinding
=
cast
<
UiScriptBinding
*>
(
m
->
member
))
{
if
(
scriptBinding
->
qualifiedId
&&
scriptBinding
->
qualifiedId
->
name
->
asString
()
==
QLatin1String
(
"target"
)
&&
!
scriptBinding
->
qualifiedId
->
next
)
{
if
(
ExpressionStatement
*
expStmt
=
cast
<
ExpressionStatement
*>
(
scriptBinding
->
statement
))
{
Evaluate
evaluator
(
&
_context
);
const
Value
*
targetValue
=
evaluator
(
expStmt
->
expression
);
if
(
const
ObjectValue
*
target
=
value_cast
<
const
ObjectValue
*>
(
targetValue
))
{
_context
.
scopeChain
().
qmlScopeObjects
.
prepend
(
target
);
}
else
{
_allowAnyProperty
=
true
;
}
}
}
}
}
}
#endif
Node
::
accept
(
initializer
,
this
);
_context
.
scopeChain
().
qmlScopeObjects
=
oldScopeObjects
;
_allowAnyProperty
=
oldAllowAnyProperty
;
_scopeBuilder
.
pop
();
}
bool
Check
::
visit
(
UiScriptBinding
*
ast
)
...
...
@@ -231,10 +180,9 @@ bool Check::visit(UiArrayBinding *ast)
const
Value
*
Check
::
checkScopeObjectMember
(
const
UiQualifiedId
*
id
)
{
if
(
_allowAnyProperty
)
return
0
;
QList
<
const
ObjectValue
*>
scopeObjects
=
_context
.
scopeChain
().
qmlScopeObjects
;
if
(
scopeObjects
.
isEmpty
())
return
0
;
if
(
!
id
)
return
0
;
// ### error?
...
...
src/libs/qmljs/qmljscheck.h
View file @
e9039db9
...
...
@@ -33,6 +33,7 @@
#include
<qmljs/qmljsdocument.h>
#include
<qmljs/qmljsinterpreter.h>
#include
<qmljs/qmljslink.h>
#include
<qmljs/qmljsscopebuilder.h>
#include
<qmljs/parser/qmljsastvisitor_p.h>
namespace
QmlJS
{
...
...
@@ -72,10 +73,9 @@ private:
Interpreter
::
Engine
_engine
;
Interpreter
::
Context
_context
;
Link
_link
;
ScopeBuilder
_scopeBuilder
;
QList
<
DiagnosticMessage
>
_messages
;
bool
_allowAnyProperty
;
};
}
// namespace QmlJS
...
...
src/libs/qmljs/qmljslink.cpp
View file @
e9039db9
...
...
@@ -3,6 +3,7 @@
#include
"parser/qmljsast_p.h"
#include
"qmljsdocument.h"
#include
"qmljsbind.h"
#include
"qmljsscopebuilder.h"
#include
<QtCore/QFileInfo>
#include
<QtCore/QDir>
...
...
@@ -44,37 +45,16 @@ void Link::scopeChainAt(Document::Ptr doc, const QList<Node *> &astPath)
Bind
*
bind
=
doc
->
bind
();
QHash
<
Document
*
,
ScopeChain
::
QmlComponentChain
*>
componentScopes
;
int
qmlScopeObjectIndex
=
-
1
;
if
(
doc
->
qmlProgram
())
{
_context
->
setLookupMode
(
Context
::
QmlLookup
);
makeComponentChain
(
doc
,
&
scopeChain
.
qmlComponentScope
,
&
componentScopes
);
// find the last object definition or object binding: that is the scope object
for
(
int
i
=
astPath
.
size
()
-
1
;
i
>=
0
;
--
i
)
{
Node
*
node
=
astPath
.
at
(
i
);
ObjectValue
*
scopeObject
=
0
;
if
(
UiObjectDefinition
*
definition
=
cast
<
UiObjectDefinition
*>
(
node
))
scopeObject
=
bind
->
findQmlObject
(
definition
);
else
if
(
UiObjectBinding
*
binding
=
cast
<
UiObjectBinding
*>
(
node
))
scopeObject
=
bind
->
findQmlObject
(
binding
);
if
(
scopeObject
)
{
if
(
scopeObject
!=
scopeChain
.
qmlComponentScope
.
rootObject
)
scopeChain
.
qmlScopeObjects
+=
scopeObject
;
qmlScopeObjectIndex
=
i
;
break
;
}
}
if
(
const
ObjectValue
*
typeEnvironment
=
_context
->
typeEnvironment
(
doc
.
data
()))
scopeChain
.
qmlTypes
=
typeEnvironment
;
}
else
{
// the global scope of a js file does not see the instantiating component
qDebug
()
<<
"ast path length: "
<<
astPath
.
size
();
if
(
astPath
.
size
()
!=
0
)
{
if
(
astPath
.
size
()
>
0
)
{
// add scope chains for all components that source this document
foreach
(
Document
::
Ptr
otherDoc
,
_docs
)
{
if
(
otherDoc
->
bind
()
->
includedScripts
().
contains
(
doc
->
fileName
()))
{
...
...
@@ -91,20 +71,9 @@ void Link::scopeChainAt(Document::Ptr doc, const QList<Node *> &astPath)
scopeChain
.
jsScopes
+=
bind
->
rootObjectValue
();
}
for
(
int
i
=
qmlScopeObjectIndex
+
1
;
i
<
astPath
.
size
();
++
i
)
{
Node
*
node
=
astPath
.
at
(
i
);
if
(
FunctionDeclaration
*
fun
=
cast
<
FunctionDeclaration
*>
(
node
))
{
ObjectValue
*
activation
=
engine
()
->
newObject
(
/*prototype = */
0
);
for
(
FormalParameterList
*
it
=
fun
->
formals
;
it
;
it
=
it
->
next
)
{
if
(
it
->
name
)
activation
->
setProperty
(
it
->
name
->
asString
(),
engine
()
->
undefinedValue
());
}
scopeChain
.
jsScopes
+=
activation
;
}
}
scopeChain
.
update
();
ScopeBuilder
scopeBuilder
(
doc
,
_context
);
foreach
(
Node
*
node
,
astPath
)
scopeBuilder
.
push
(
node
);
}
void
Link
::
makeComponentChain
(
...
...
src/libs/qmljs/qmljsscopebuilder.cpp
0 → 100644
View file @
e9039db9
#include
"qmljsscopebuilder.h"
#include
"qmljsbind.h"
#include
"qmljsinterpreter.h"
#include
"qmljsevaluate.h"
#include
"parser/qmljsast_p.h"
using
namespace
QmlJS
;
using
namespace
QmlJS
::
Interpreter
;
using
namespace
QmlJS
::
AST
;
ScopeBuilder
::
ScopeBuilder
(
Document
::
Ptr
doc
,
Interpreter
::
Context
*
context
)
:
_doc
(
doc
)
,
_context
(
context
)
{
}
ScopeBuilder
::~
ScopeBuilder
()
{
}
void
ScopeBuilder
::
push
(
AST
::
Node
*
node
)
{
_nodes
+=
node
;
// QML scope object
Node
*
qmlObject
=
cast
<
UiObjectDefinition
*>
(
node
);
if
(
!
qmlObject
)
qmlObject
=
cast
<
UiObjectBinding
*>
(
node
);
if
(
qmlObject
)
setQmlScopeObject
(
qmlObject
);
// JS scopes
if
(
FunctionDeclaration
*
fun
=
cast
<
FunctionDeclaration
*>
(
node
))
{
ObjectValue
*
activation
=
_context
->
engine
()
->
newObject
(
/*prototype = */
0
);
for
(
FormalParameterList
*
it
=
fun
->
formals
;
it
;
it
=
it
->
next
)
{
if
(
it
->
name
)
activation
->
setProperty
(
it
->
name
->
asString
(),
_context
->
engine
()
->
undefinedValue
());
}
_context
->
scopeChain
().
jsScopes
+=
activation
;
}
_context
->
scopeChain
().
update
();
}
void
ScopeBuilder
::
pop
()
{
Node
*
toRemove
=
_nodes
.
last
();
_nodes
.
removeLast
();
// JS scopes
if
(
cast
<
FunctionDeclaration
*>
(
toRemove
))
_context
->
scopeChain
().
jsScopes
.
removeLast
();
// QML scope object
if
(
!
_nodes
.
isEmpty
()
&&
(
cast
<
UiObjectDefinition
*>
(
toRemove
)
||
cast
<
UiObjectBinding
*>
(
toRemove
)))
setQmlScopeObject
(
_nodes
.
last
());
_context
->
scopeChain
().
update
();
}
void
ScopeBuilder
::
setQmlScopeObject
(
Node
*
node
)
{
ScopeChain
&
scopeChain
=
_context
->
scopeChain
();
scopeChain
.
qmlScopeObjects
.
clear
();
const
ObjectValue
*
scopeObject
=
_doc
->
bind
()
->
findQmlObject
(
node
);
if
(
scopeObject
)
{
if
(
scopeObject
!=
scopeChain
.
qmlComponentScope
.
rootObject
)
scopeChain
.
qmlScopeObjects
+=
scopeObject
;
}
#ifndef NO_DECLARATIVE_BACKEND
// check if the object has a Qt.ListElement ancestor
const
ObjectValue
*
prototype
=
scopeObject
->
prototype
(
_context
);
while
(
prototype
)
{
if
(
const
QmlObjectValue
*
qmlMetaObject
=
dynamic_cast
<
const
QmlObjectValue
*>
(
prototype
))
{
// ### Also check for Qt package. Involves changes in QmlObjectValue.
if
(
qmlMetaObject
->
qmlTypeName
()
==
QLatin1String
(
"ListElement"
))
{
scopeChain
.
qmlScopeObjects
.
clear
();
break
;
}
}
prototype
=
prototype
->
prototype
(
_context
);
}
// check if the object has a Qt.PropertyChanges ancestor
prototype
=
scopeObject
->
prototype
(
_context
);
while
(
prototype
)
{
if
(
const
QmlObjectValue
*
qmlMetaObject
=
dynamic_cast
<
const
QmlObjectValue
*>
(
prototype
))
{
// ### Also check for Qt package. Involves changes in QmlObjectValue.
if
(
qmlMetaObject
->
qmlTypeName
()
==
QLatin1String
(
"PropertyChanges"
))
break
;
}
prototype
=
prototype
->
prototype
(
_context
);
}
// find the target script binding
if
(
prototype
)
{
UiObjectInitializer
*
initializer
=
0
;
if
(
UiObjectDefinition
*
definition
=
cast
<
UiObjectDefinition
*>
(
node
))
initializer
=
definition
->
initializer
;
if
(
UiObjectBinding
*
binding
=
cast
<
UiObjectBinding
*>
(
node
))
initializer
=
binding
->
initializer
;
if
(
initializer
)
{
for
(
UiObjectMemberList
*
m
=
initializer
->
members
;
m
;
m
=
m
->
next
)
{
if
(
UiScriptBinding
*
scriptBinding
=
cast
<
UiScriptBinding
*>
(
m
->
member
))
{
if
(
scriptBinding
->
qualifiedId
&&
scriptBinding
->
qualifiedId
->
name
->
asString
()
==
QLatin1String
(
"target"
)
&&
!
scriptBinding
->
qualifiedId
->
next
)
{
// ### make Evaluate understand statements.
if
(
ExpressionStatement
*
expStmt
=
cast
<
ExpressionStatement
*>
(
scriptBinding
->
statement
))
{
Evaluate
evaluator
(
_context
);
const
Value
*
targetValue
=
evaluator
(
expStmt
->
expression
);
if
(
const
ObjectValue
*
target
=
value_cast
<
const
ObjectValue
*>
(
targetValue
))
{
scopeChain
.
qmlScopeObjects
.
prepend
(
target
);
}
else
{
scopeChain
.
qmlScopeObjects
.
clear
();
}
}
}
}
}
}
}
#endif
}
src/libs/qmljs/qmljsscopebuilder.h
0 → 100644
View file @
e9039db9
#ifndef QMLJSSCOPEBUILDER_H
#define QMLJSSCOPEBUILDER_H
#include
<qmljs/qmljsdocument.h>
#include
<QtCore/QList>
namespace
QmlJS
{
namespace
AST
{
class
Node
;
}
namespace
Interpreter
{
class
Context
;
}
class
ScopeBuilder
{
public:
ScopeBuilder
(
Document
::
Ptr
doc
,
Interpreter
::
Context
*
context
);
~
ScopeBuilder
();
void
push
(
AST
::
Node
*
node
);
void
pop
();
private:
void
setQmlScopeObject
(
AST
::
Node
*
node
);
Document
::
Ptr
_doc
;
Interpreter
::
Context
*
_context
;
QList
<
AST
::
Node
*>
_nodes
;
};
}
// namespace QmlJS
#endif // QMLJSSCOPEBUILDER_H
Write
Preview
Supports
Markdown
0%
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!
Cancel
Please
register
or
sign in
to comment