Commit 905f2e62 authored by Olivier Goffart's avatar Olivier Goffart
Browse files

Merge remote branch 'origin/master' into qmljsinspector

Conflicts:
	src/plugins/qmlinspector/qmlinspector.cpp
parents 95b06415 1430358d
......@@ -77,6 +77,7 @@ bin/qtcreator_process_stub*
bin/qtcreator.exe
share/doc/qtcreator/qtcreator.qch
tests/manual/cplusplus/cplusplus0
tests/manual/cplusplus-dump/cplusplus0
tests/auto/qml/qmldesigner/bauhaustests/tst_bauhaus
tests/auto/qml/qmldesigner/coretests/tst_qmldesigner_core
tests/auto/qml/qmldesigner/propertyeditortests/tst_propertyeditor
......
doc/images/qmldesigner-helloworld.png

18.9 KB | W: | H:

doc/images/qmldesigner-helloworld.png

9.73 KB | W: | H:

doc/images/qmldesigner-helloworld.png
doc/images/qmldesigner-helloworld.png
doc/images/qmldesigner-helloworld.png
doc/images/qmldesigner-helloworld.png
  • 2-up
  • Swipe
  • Onion skin
This diff is collapsed.
......@@ -57,6 +57,11 @@ qhp.QtCreator.extraFiles = \
images/qt-logo.png \
images/sprites-combined.png
qhp.QtCreator.subprojects = manual
qhp.QtCreator.subprojects.manual.title = Qt Creator Manual
qhp.QtCreator.subprojects.manual.indexTitle = Qt Creator Manual
qhp.QtCreator.subprojects.manual.type = manual
# macros.qdocconf
macro.aring.HTML = "å"
......
......@@ -11,3 +11,4 @@ TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS = src share
WITH_TESTS:SUBDIRS += tests
......@@ -92,12 +92,43 @@ typeCache = {}
def lookupType(typestring):
type = typeCache.get(typestring)
#warn("LOOKUP: %s -> %s" % (typestring, type))
#warn("LOOKUP 1: %s -> %s" % (typestring, type))
if type is None:
type = gdb.lookup_type(typestring)
ts = typestring
while True:
#WARN("ts: '%s'" % ts)
if ts.startswith("class "):
ts = ts[6:]
elif ts.startswith("struct "):
ts = ts[7:]
elif ts.startswith("const "):
ts = ts[6:]
elif ts.startswith("volatile "):
ts = ts[9:]
elif ts.startswith("enum "):
ts = ts[5:]
elif ts.endswith("const"):
ts = ts[-5:]
elif ts.endswith("volatile"):
ts = ts[-8:]
else:
break
try:
#warn("LOOKING UP '%s'" % ts)
type = gdb.lookup_type(ts)
except:
# Can throw "RuntimeError: No type named class Foo."
#warn("LOOKING UP '%s' FAILED" % ts)
pass
#warn(" RESULT: '%s'" % type)
#if not type is None:
# warn(" FIELDS: '%s'" % type.fields())
typeCache[typestring] = type
return type
def cleanType(type):
return lookupType(str(type))
def cleanAddress(addr):
if addr is None:
return "<no address>"
......@@ -595,6 +626,10 @@ def stripClassTag(type):
return type[6:]
elif type.startswith("struct "):
return type[7:]
elif type.startswith("const "):
return type[6:]
elif type.startswith("volatile "):
return type[9:]
return type
def checkPointerRange(p, n):
......@@ -755,12 +790,27 @@ def encodeString(value):
p += 1
return s
def stripTypedefs(typeobj):
type = typeobj
def stripTypedefs(type):
type = type.unqualified()
while type.code == gdb.TYPE_CODE_TYPEDEF:
type = type.strip_typedefs().unqualified()
return type
def extractFields(type):
# Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=10953:
#fields = value.type.fields()
# Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=11777:
#fields = stripTypedefs(value.type).fields()
# This seems to work.
#warn("TYPE 0: %s" % type)
type = stripTypedefs(type)
#warn("TYPE 1: %s" % type)
type = lookupType(str(type))
#warn("TYPE 2: %s" % type)
fields = type.fields()
#warn("FIELDS: %s" % fields)
return fields
#######################################################################
#
# Item
......@@ -1114,7 +1164,7 @@ class Dumper:
self.put('{name="<incomplete>",value="",type="",numchild="0"},')
def putType(self, type, priority = 0):
# higher priority values override lower ones
# Higher priority values override lower ones.
if priority >= self.currentTypePriority:
self.currentType = type
self.currentTypePriority = priority
......@@ -1300,13 +1350,22 @@ class Dumper:
isHandled = False
target = stripTypedefs(type.target())
if (not isHandled) and isNull(value):
#warn("NULL POINTER")
self.putType(item.value.type)
self.putValue("0x0")
self.putNumChild(0)
isHandled = True
if (not isHandled) and target.code == gdb.TYPE_CODE_VOID:
#warn("VOID POINTER: %s" % format)
self.putType(item.value.type)
self.putValue(str(value))
self.putNumChild(0)
isHandled = True
if (not isHandled) and (not format is None):
#warn("SPECIAL FORMAT POINTER: %s" % format)
self.putAddress(value.address)
self.putType(item.value.type)
isHandled = True
......@@ -1328,10 +1387,8 @@ class Dumper:
self.putValue(encodeChar4Array(value, 100), Hex8EncodedBigEndian)
self.putNumChild(0)
if (not isHandled):
anonStrippedType = str(typedefStrippedType) \
.replace("(anonymous namespace)", "")
if anonStrippedType.find("(") != -1:
if (not isHandled) and (str(typedefStrippedType)
.replace("(anonymous namespace)", "").find("(") != -1):
# A function pointer.
self.putValue(str(item.value))
self.putAddress(value.address)
......@@ -1339,19 +1396,6 @@ class Dumper:
self.putNumChild(0)
isHandled = True
if (not isHandled) and self.useFancy:
if isNull(value):
self.putValue("0x0")
self.putType(item.value.type)
self.putNumChild(0)
isHandled = True
if (not isHandled):
self.putType(item.value.type)
self.putValue(str(value))
self.putNumChild(0)
isHandled = True
#warn("AUTODEREF: %s" % self.autoDerefPointers)
#warn("IS HANDLED: %s" % isHandled)
#warn("RES: %s" % (self.autoDerefPointers and not isHandled))
......@@ -1396,17 +1440,7 @@ class Dumper:
#warn("INAME: %s " % item.iname)
#warn("INAMES: %s " % self.expandedINames)
#warn("EXPANDED: %s " % (item.iname in self.expandedINames))
# Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=10953
#fields = value.type.fields()
# Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=11777
#fields = stripTypedefs(value.type).fields()
# This seems to work.
type = stripTypedefs(type)
type = lookupType(str(type))
fields = type.fields()
fields = extractFields(type)
self.putType(item.value.type)
try:
......@@ -1444,9 +1478,7 @@ class Dumper:
def putFields(self, item, innerType = None):
value = item.value
type = stripTypedefs(value.type)
# http://sourceware.org/bugzilla/show_bug.cgi?id=11777
type = lookupType(str(type))
fields = stripTypedefs(type).fields()
fields = extractFields(type)
baseNumber = 0
for field in fields:
#warn("FIELD: %s" % field)
......
......@@ -665,30 +665,31 @@ def qdump__QObject(d, item):
if d.isExpandedIName(item.iname + ".properties"):
with Children(d, [propertyCount, 500]):
# Dynamic properties.
dummyType = lookupType("void").pointer().pointer()
namesType = lookupType(d.ns + "QByteArray")
valuesBegin = values["d"]["begin"]
valuesEnd = values["d"]["end"]
valuesArray = values["d"]["array"]
valuesType = lookupType(d.ns + "QVariant")
p = namesArray.cast(dummyType) + namesBegin
q = valuesArray.cast(dummyType) + valuesBegin
for i in xrange(dynamicPropertyCount):
with SubItem(d):
pp = p.cast(namesType.pointer()).dereference();
d.putField("key", encodeByteArray(pp))
d.putField("keyencoded", Hex2EncodedLatin1)
qq = q.cast(valuesType.pointer().pointer())
qq = qq.dereference();
d.putField("addr", cleanAddress(qq))
d.putField("exp", "*('%sQVariant'*)%s"
% (d.ns, cleanAddress(qq)))
name = "%s.properties.%d" % (item.iname, i)
t = qdump__QVariant(d, Item(qq, name))
# Override the "QVariant (foo)" output
d.putType(t, d.currentTypePriority + 1)
p += 1
q += 1
if dynamicPropertyCount != 0:
dummyType = lookupType("void").pointer().pointer()
namesType = lookupType(d.ns + "QByteArray")
valuesBegin = values["d"]["begin"]
valuesEnd = values["d"]["end"]
valuesArray = values["d"]["array"]
valuesType = lookupType(d.ns + "QVariant")
p = namesArray.cast(dummyType) + namesBegin
q = valuesArray.cast(dummyType) + valuesBegin
for i in xrange(dynamicPropertyCount):
with SubItem(d):
pp = p.cast(namesType.pointer()).dereference();
d.putField("key", encodeByteArray(pp))
d.putField("keyencoded", Hex2EncodedLatin1)
qq = q.cast(valuesType.pointer().pointer())
qq = qq.dereference();
d.putField("addr", cleanAddress(qq))
d.putField("exp", "*('%sQVariant'*)%s"
% (d.ns, cleanAddress(qq)))
name = "%s.properties.%d" % (item.iname, i)
t = qdump__QVariant(d, Item(qq, name))
# Override the "QVariant (foo)" output
d.putType(t, d.currentTypePriority + 1)
p += 1
q += 1
# Static properties.
propertyData = metaData[7]
......@@ -798,6 +799,28 @@ def qdump__QObject(d, item):
d.putType(" ")
d.putValue(extractCString(metaStringData, offset))
# Active connection
with SubItem(d):
d.putName("currentSender")
d.putType(" ")
sender = d_ptr["currentSender"]
d.putValue(cleanAddress(sender))
if isNull(sender):
d.putNumChild(0)
else:
d.putNumChild(1)
iname = item.iname + ".currentSender"
if d.isExpandedIName(iname):
with Children(d):
# Sending object
d.putItem(Item(sender["sender"], iname, "object", "object"))
# Signal in sending object
with SubItem(d):
d.putName("signal")
d.putValue(sender["signal"])
d.putType(" ");
d.putNumChild(0)
# QObject
# static const uint qt_meta_data_QObject[] = {
......
......@@ -145,7 +145,8 @@ class qdebug:
self.put("children=[")
self.dumpValue(k, "key", "%s.%d.k" % (iname, i))
self.dumpValue(v, "value", "%s.%d.v" % (iname, i))
self.put("]},")
self.put("]")
self.put("},")
i += 1
self.put("]")
elif tt == "class":
......
QT -= core
QT = core
%NETWORK%QT += network
CONFIG += console
CONFIG -= app_bundle
......
......@@ -29,9 +29,9 @@
**
**************************************************************************/
Custom project wizard configuration example file. Note that by convention,
Custom project wizard configuration example file. Note that by convention,
the project file goes last.
The "class" and "firstpage" attributes specify that it is a Qt 4 wizard and
The "class" and "firstpage" attributes specify that it is a Qt 4 wizard and
leave room for the Qt 4 target page.
-->
<wizard version="1" kind="project"
......@@ -55,5 +55,11 @@ leave room for the Qt 4 target page.
<fielddescription>Hello world message:</fielddescription>
<fielddescription xml:lang="de">Hallo-Welt-Nachricht:</fielddescription>
</field>
<!-- Comment out network in profile according to user's wishes -->
<field name="NETWORK">
<fieldcontrol class="QCheckBox" truevalue="" falsevalue="# "/>
<fielddescription>Include network module</fielddescription>
<fielddescription xml:lang="de">Netzwerk-Modul verwenden</fielddescription>
</field>
</fields>
</wizard>
......@@ -51,7 +51,18 @@ Custom class wizard example configuration file. -->
<fielddescription xml:lang="de">Klassenname:</fielddescription>
</field>
<field name="Datatype">
<fieldcontrol class="QComboBox" combochoices="QString,int" defaultindex="0" />
<fieldcontrol class="QComboBox" defaultindex="0">
<comboentries>
<comboentry value="QString">
<comboentrytext>class QString</comboentrytext>
<comboentrytext xml:lang="de">Klasse QString</comboentrytext>
</comboentry>
<comboentry value="int">
<comboentrytext>Integer</comboentrytext>
<comboentrytext xml:lang="de">Ganzzahlwert</comboentrytext>
</comboentry>
</comboentries>
</fieldcontrol>
<fielddescription>Data type:</fielddescription>
<fielddescription xml:lang="de">Datentyp:</fielddescription>
</field>
......
......@@ -5,5 +5,5 @@ where empty($files)
return
for $file in $files
let $doc := doc($file)
for $text in ($doc/*:wizard/*:description, $doc/*:wizard/*:displayname, $doc/*:wizard/*:displaycategory, $doc/*:wizard/*:fieldpagetitle, $doc/*:wizard/*:fields/*:field/*:fielddescription)
for $text in ($doc/*:wizard/*:description, $doc/*:wizard/*:displayname, $doc/*:wizard/*:displaycategory, $doc/*:wizard/*:fieldpagetitle, $doc/*:wizard/*:fields/*:field/*:fielddescription, $doc/*:wizard/*:fields/*:field/*:fieldcontrol/*:comboentries/*:comboentry/*:comboentrytext)
return fn:concat($prefix, data($text), $suffix)
......@@ -44,7 +44,12 @@ QList<AST *> ASTPath::operator()(int line, int column)
_nodes.clear();
_line = line + 1;
_column = column + 1;
accept(_doc->translationUnit()->ast());
if (_doc) {
if (TranslationUnit *unit = _doc->translationUnit())
accept(unit->ast());
}
return _nodes;
}
......
......@@ -27,83 +27,61 @@
**
**************************************************************************/
#include "BackwardsScanner.h"
#include "TokenCache.h"
#include <Token.h>
#include <QtGui/QTextCursor>
#include <QTextDocument>
using namespace CPlusPlus;
BackwardsScanner::BackwardsScanner(TokenCache *tokenCache, const QTextCursor &cursor, int maxBlockCount, const QString &suffix)
: _tokenCache(tokenCache)
, _offset(0)
BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, int maxBlockCount, const QString &suffix)
: _offset(0)
, _blocksTokenized(0)
, _block(cursor.block())
, _maxBlockCount(maxBlockCount)
{
int pos = cursor.position() - cursor.block().position();
_text = _block.text().left(pos);
_text += suffix;
_tokenize.setQtMocRunEnabled(true);
_tokenize.setSkipComments(true);
_tokenize.setObjCEnabled(true);
_text = _block.text().left(cursor.position() - cursor.block().position());
_tokens.append(tokenCache->tokensForBlock(_block));
if (! suffix.isEmpty())
_text += suffix;
for (int i = _tokens.size() - 1; i >= 0; --i) {
const int tokenEnd = _tokens.at(i).end();
if ((tokenEnd < pos) ||
(tokenEnd == pos && suffix.isEmpty())) {
break;
} else {
_tokens.removeAt(i);
}
}
QString remainingText;
if (!_tokens.isEmpty())
remainingText = _text.mid(_tokens.last().end());
if (!remainingText.isEmpty()) {
SimpleLexer tokenize;
tokenize.setQtMocRunEnabled(true);
tokenize.setSkipComments(true);
tokenize.setObjCEnabled(true);
_tokens.append(tokenize(remainingText, TokenCache::previousBlockState(_block)));
}
_tokens.append(_tokenize(_text, previousBlockState(_block)));
_startToken = _tokens.size();
}
SimpleToken BackwardsScanner::LA(int index) const
Token BackwardsScanner::LA(int index) const
{ return const_cast<BackwardsScanner *>(this)->fetchToken(_startToken - index); }
SimpleToken BackwardsScanner::operator[](int index) const
Token BackwardsScanner::operator[](int index) const
{ return const_cast<BackwardsScanner *>(this)->fetchToken(index); }
const SimpleToken &BackwardsScanner::fetchToken(int tokenIndex)
const Token &BackwardsScanner::fetchToken(int tokenIndex)
{
while (_offset + tokenIndex < 0) {
_block = _block.previous();
if (_blocksTokenized == _maxBlockCount || !_block.isValid()) {
++_offset;
_tokens.prepend(SimpleToken()); // sentinel
_tokens.prepend(Token()); // sentinel
break;
} else {
++_blocksTokenized;
QList<SimpleToken> newTokens = _tokenCache->tokensForBlock(_block);
QString blockText = _block.text();
_text.prepend(QLatin1Char('\n'));
_text.prepend(blockText);
QList<SimpleToken> adaptedTokens;
QList<Token> adaptedTokens;
for (int i = 0; i < _tokens.size(); ++i) {
SimpleToken t = _tokens.at(i);
t.setPosition(t.position() + blockText.length() + 1);
Token t = _tokens.at(i);
t.offset += + blockText.length() + 1;
adaptedTokens.append(t);
}
_tokens = newTokens;
_offset += newTokens.size();
_tokens = _tokenize(blockText, previousBlockState(_block));
_offset += _tokens.size();
_tokens += adaptedTokens;
}
}
......@@ -122,19 +100,19 @@ QString BackwardsScanner::text() const
QString BackwardsScanner::mid(int index) const
{
const SimpleToken &firstToken = _tokens.at(index + _offset);
const Token &firstToken = _tokens.at(index + _offset);
return _text.mid(firstToken.begin());
}
QString BackwardsScanner::text(int index) const
{
const SimpleToken &firstToken = _tokens.at(index + _offset);
const Token &firstToken = _tokens.at(index + _offset);
return _text.mid(firstToken.begin(), firstToken.length());
}
QStringRef BackwardsScanner::textRef(int index) const
{
const SimpleToken &firstToken = _tokens.at(index + _offset);
const Token &firstToken = _tokens.at(index + _offset);
return _text.midRef(firstToken.begin(), firstToken.length());
}
......@@ -203,11 +181,11 @@ int BackwardsScanner::startOfLine(int index) const
const BackwardsScanner tk(*this);
forever {
const SimpleToken &tok = tk[index - 1];
const Token &tok = tk[index - 1];
if (tok.is(T_EOF_SYMBOL))
break;
else if (tok.followsNewline())
else if (tok.newline())
return index - 1;
--index;
......@@ -223,7 +201,7 @@ int BackwardsScanner::startOfBlock(int index) const
const int start = index;
forever {
SimpleToken token = tk[index - 1];
Token token = tk[index - 1];
if (token.is(T_EOF_SYMBOL)) {
break;
......@@ -256,7 +234,23 @@ int BackwardsScanner::startOfBlock(int index) const
QString BackwardsScanner::indentationString(int index) const
{
const SimpleToken tokenAfterNewline = operator[](startOfLine(index + 1));
const int newlinePos = qMax(0, _text.lastIndexOf(QLatin1Char('\n'), tokenAfterNewline.position()));
return _text.mid(newlinePos, tokenAfterNewline.position() - newlinePos);
const Token tokenAfterNewline = operator[](startOfLine(index + 1));
const int newlinePos = qMax(0, _text.lastIndexOf(QLatin1Char('\n'),
tokenAfterNewline.begin()));
return _text.mid(newlinePos, tokenAfterNewline.begin() - newlinePos);
}
int BackwardsScanner::previousBlockState(const QTextBlock &block)
{
const QTextBlock prevBlock = block.previous();
if (prevBlock.isValid()) {
int state = prevBlock.userState();
if (state != -1)
return state;
}
return 0;
}
......@@ -36,15 +36,12 @@
namespace CPlusPlus {
class TokenCache;
class CPLUSPLUS_EXPORT BackwardsScanner
{
enum { MAX_BLOCK_COUNT = 10 };
public:
BackwardsScanner(TokenCache *cache,
const QTextCursor &cursor,
BackwardsScanner(const QTextCursor &cursor,
int maxBlockCount = MAX_BLOCK_COUNT,
const QString &suffix = QString());
......@@ -58,10 +55,10 @@ public:
QString text(int index) const;
QStringRef textRef(int index) const;
// 1-based
SimpleToken LA(int index) const;
Token LA(int index) const;
// n-la token is [startToken - n]
SimpleToken operator[](int index) const; // ### deprecate
Token operator[](int index) const; // ### deprecate
QString indentationString(int index) const;
......@@ -71,15 +68,17 @@ public: