Merge remote-tracking branch 'gerrit/3.2'

Change-Id: I2567b8f19e502777f6566ce573a6970fb62a7521
This commit is contained in:
Eike Ziller
2014-07-07 17:57:23 +02:00
212 changed files with 2738 additions and 1478 deletions

74
dist/changes-3.2.0 vendored
View File

@@ -15,17 +15,20 @@ General
* Enabled resizing of the locator field
* Improved look and feel on HiDPI by adding more hi-resolution icons
* Made keyboard and mouse activation of navigation panes and other trees more consistent
* Added display of current variable values in variable chooser dialog
* Removed unhelpful Generic Highlighter loading progress bar
Editing
* Fixed support for mixed languages in the generic highlighter
Managing and Building Projects
QMake Projects
* Added context menu item for copying resource path from entries in QRC files in project tree
(QTCREATORBUG-11776)
* Added context menu item for copying resource path from entries in QRC
files in project tree (QTCREATORBUG-11776)
* Added deployment support to plain C and C++ application wizards
* Removed warning about build directory below source directory for kits with Qt 5.2 and later
where this is supported (QTCREATORBUG-10024)
* Removed warning about build directory below source directory for kits
with Qt 5.2 and later where this is supported (QTCREATORBUG-10024)
* Fixed that adding files to .pri file was missing $$PWD
Qbs Projects
@@ -37,12 +40,49 @@ Qbs Projects
Generic Projects
Debugging
* Added option to disable automatic centering on currently debugged line in editor
* GDB and LLDB
* Added pretty printers for AVX512 registers
* Changed default of "Load system GDB pretty printer" option back to "off"
* Added option to disable automatic centering on currently debugged
line in editor
* Made environment variables accessible in startup command settings
using a %{Env:SOME_NAME} syntax
* Changed single click on column view headers to cycle through
a "small widget" and a "width according to contents"
* Removed the "Always adjust to content size options" and
made this the default behavior
* Added pretty printers for AVX512 registers
* Fixed display of fixed-size wchar_t arrays
* Added personaltypes.py as default location for user created dumpers
* Added file setting to point to user created file of dumpers
(QTCREATORBUG-12492)
* Added button to restart current debugging session
without quitting the debugger process
* Made our dumpers also accessible from command line GDB
* Made LLDB engine honor the max stack depth setting
(QTCREATORBUG-12416)
* Added dumpers for QStringData, QHashedString and QQmlRefCount
* Fixed CDB engine to reset Locals and Expressions when
switching frames
* Made LLDB engine recover more gracefully from unexpected
situations
* Improved handling of the tabbed extra views for displayed
items
* Fixed regression in process snapshot creation
* Fixed crash in CDB extension related to verbose logs
* Introduced option to limit retrieval of string-like values
* Introduced [a..b] and [a.(s).b] syntax for more flexibility
in "ranged" expressions in Locals and Expression view
* Added several convienience functions to Python dumper interface
* Fixed CDB detection for Windows SDK 8.1
* Added raw opcode bytes to Disassembler view
* Changed Disassembler view to order lines by increasing address
* Made more dumpers work in release builds
* Fixed debugging applications that are run in a terminal on Linux (QTCREATORBUG-3509)
QML Profiler
Analyzer
* Added support for Run in Terminal (QTCREATORBUG-7311)
C++ Support
* Fixed finding usages of members of typedef'ed anonymous structs
(QTCREATORBUG-11859, QTCREATORBUG-11860)
@@ -57,12 +97,23 @@ Qt Quick Designer
Diff Viewer
Version Control Systems
* Git
* Fixed replies to prompts (QTCREATORBUG-12335)
* Fixed that original author was not preserved during Cherry-Pick
* Reintroduced the expanded branch list in Show (QTCREATORBUG-11293)
* Fixed that switching to the commit editor was unresponsive (QTCREATORBUG-12449)
* Fixed showing commits by clicking their hashes in the interactive rebase editor
* Improved display in the Gerrit dialog to visualize dependencies
* Added support for choosing reviewer in Push to Gerrit dialog
over HTTP
FakeVim
* Added support for unicode input with 'C-v' in insert mode
* Fixed issues with long command output (QTCREATORBUG-11598)
* Fixed 'gv' after yanking text in visual mode (QTCREATORBUG-12112)
* Fixed 'v', 'V' and 'C-v' while in visual mode (QTCREATORBUG-12113)
* Improved sharing of navigation data between editors of the
same document
Platform Specific
@@ -75,9 +126,18 @@ OS X
Android
* Fixed that UI was unresponsive while creating AVD (QTCREATORBUG-10601)
Remote Linux
* Added custom remote executable run configuration type (QTCREATORBUG-12168)
* Fixed issue with environment variables that contain spaces
BareMetal:
* Added openocd pipelining support
* Added variable support for device specific GDB commands
Valgrind:
* Fixed passing of multiple arguments to application
Credits for these changes go to:

View File

@@ -692,6 +692,139 @@
\note As an exception, imported third party code as well as code
interfacing the native APIs (src/support/os_*) can use NULL.
\section2 C++11 Features
Code should compile with Microsoft Visual Studio 2010, g++ 4.5, and Clang 3.1.
\section3 Lambdas
You can use lambdas with the following restrictions:
\list
\li You have to explicitly specify the return type, if the lambda contains more than a
single expression. Otherwise it does not compile with VS2010.
\code
[]() -> QString {
Foo *foo = activeFoo();
return foo ? foo->displayName() : QString();
});
-NOT-
[]() {
Foo *foo = activeFoo();
return foo ? foo->displayName() : QString();
});
\endcode
\li If you use static functions from the class that the lambda is located in, you have to
explicitly capture \c this. Otherwise it does not compile with g++ 4.7 and earlier.
\code
void Foo::something()
{
...
[this]() { Foo::someStaticFunction(); }
...
}
-NOT-
void Foo::something()
{
...
[]() { Foo::someStaticFunction(); }
...
}
\endcode
\endlist
Format the lambda according to the following rules:
\list
\li Always write parentheses for the parameter list, even if the function does not take
parameters.
\code
[]() { doSomething(); }
-NOT
[] { doSomething(); }
\endcode
\li Place the capture-list, parameter list, return type, and opening brace on the first line,
the body indented on the following lines, and the closing brace on a new line.
\code
[]() -> bool {
something();
return isSomethingElse();
}
-NOT-
[]() -> bool { something();
somethingElse(); }
\endcode
\li Place a closing parenthesis and semicolon of an enclosing function call on the same line
as the closing brace of the lambda.
\code
foo([]() {
something();
});
\endcode
\li If you are using a lambda in an 'if' statement, start the lambda on a new line, to
avoid confusion between the opening brace for the lambda and the opening brace for the
'if' statement.
\code
if (anyOf(fooList,
[](Foo foo) {
return foo.isGreat();
}) {
return;
}
-NOT-
if (anyOf(fooList, [](Foo foo) {
return foo.isGreat();
}) {
return;
}
\endcode
\li Optionally, place the lambda completely on one line if it fits.
\code
foo([]() { return true; });
if (foo([]() { return true; })) {
...
}
\endcode
\endlist
\section3 \c auto Keyword
Optionally, you can use the \c auto keyword in the following cases. If in doubt,
for example if using \c auto could make the code less readable, do not use \c auto.
Keep in mind that code is read much more often than written.
\list
\li When it avoids repetition of a type in the same statement.
\code
auto something = new MyCustomType;
auto keyEvent = static_cast<QKeyEvent *>(event);
auto myList = QStringList() << QLatin1String(“FooThing”) << QLatin1String(“BarThing”);
\endcode
\li When assigning iterator types.
\code
auto it = myList.const_iterator();
\endcode
\endlist
\section2 Using QObject
\list

View File

@@ -31,8 +31,8 @@
\section2 Main Tag
The root tag is \c plugin. It has the mandatory attributes \c name
and \c version, and the optional attributes \c compatVersion, \c experimental
and \c disabledByDefault.
and \c version, and the optional attributes \c compatVersion, \c experimental,
\c disabledByDefault and \c required.
\table
\header
\li Tag
@@ -79,6 +79,12 @@
If set, the respective plugin is not loaded by default but must be explicitly
enabled by the user. This should be done for plugins which are not expected
to be used by so many people as to justify the additional resource consumption.
\row
\li required
\li Optional. Can be \c true or \c false, defaults to \c false.
Is used as a hint for the \gui{About Plugins...} dialog, that the user may not
manually disable this plugin. Only used for the Core plugin.
\endtable
\section2 Plugin-describing Tags

View File

@@ -17,6 +17,7 @@ macro.oslash.HTML = "&oslash;"
macro.ouml.HTML = "&ouml;"
macro.QA = "Qt Assistant"
macro.QC = "Qt Creator"
macro.QCE = "Qt Creator Enterprise"
macro.QD = "Qt Designer"
macro.QL = "Qt Linguist"
macro.QMLD = "Qt Quick Designer"

View File

@@ -1,5 +1,6 @@
project = "QtCreator"
description = "Qt Creator Manual"
url = http://qt-project.org/doc/qtcreator
headerdirs =
sourcedirs = $SRCDIR/src

View File

@@ -94,39 +94,10 @@
\section1 Analyzing Collected Data
The \gui Timeline view displays graphical representations of:
The \gui Timeline view displays graphical representations of QML and
JavaScript execution and a condensed view of all recorded events.
\list
\if defined(enterprise)
\li Pixmap loading times and cache sizes
\li Scene graph events
\endif
\li Painting operations
\li Compiling the QML sources
\li Creating items using QML types
\li Binding evaluations
\li Signal handling
\li Executing JavaScript behind bindings and signal handlers
\li Summary of the recorded period
\endlist
\if defined(enterprise)
Information about the pixmap cache and scene graph events are only available
from Qt 5.1 onwards.
\image qtcreator-qml-performance-monitor-enterprise.png "QML Profiler"
\else
\image qtcreator-qml-performance-monitor.png "QML Profiler"
\endif
Each row in the timeline (6) describes a type of QML events that were
recorded. Move the cursor on an event on a row to see how long it takes and
@@ -162,28 +133,132 @@
To remove an event range, close the \gui Selection dialog.
\section2 Evaluating Bindings
\section2 Understanding the Data
On the \gui Binding row, you can see when a binding is evaluated and how
long the evaluation takes. Move the mouse over the binding for details
about the binding: location in the source code, duration, and source
code.
Generally, events in the timeline view indicate how long QML or JavaScript
execution took. Move the mouse over them to see details. For most events,
they include location in source code, duration and some relevant parts of
the source code itself.
Click the binding to move the cursor in the code editor to the part of the
code where the binding is called.
You can click on an event to move the cursor in the code editor to the part
of the code the event is associated with.
\section2 Evaluating JavaScript Events
The following types of events are displayed in the timeline view on one or
several rows. The availability of event types depends on the version of Qt
the application was compiled with, the version of Qt Quick it is using, and
whether \QC or \QCE is used to profile it.
On the \gui JavaScript row, you can see the time spent executing the actual
JavaScript behind bindings and signal handlers. It lists all the JavaScript
functions you may be using to evaluate bindings or handle signals.
\table
This information is displayed for applications that use the V4 engine and
are built with Qt 5.3, or later.
\header
\li Event Type
\li Description
\li Minimum Qt Version
\li Qt Quick Version
\li Enterprise Feature
For applications that use the V8 engine and are built with Qt 5.0 or 5.1,
you can view information about JavaScript events in the \gui JavaScript
view.
\row
\li \gui {Pixmap Cache}
\li Displays the general amount of pixmap data cached, in pixels. In
addition, displays a separate event for each picture being loaded,
with specifics about its file name and size.
\li Qt 5.1
\li Qt Quick 2
\li Yes
\row
\li \gui {Scene Graph}
\li Displays the time when scene graph frames are rendered and some
additional timing information for the various stages executed to do
so.
\li Qt 5.1
\li Qt Quick 2
\li Yes
\row
\li \gui {Memory Usage}
\li Displays block allocations of the JavaScript memory manager.
Generally, the memory manager will reserve larger blocks of memory
in one piece and later hand them out to the application in smaller
bits. If the application requests single blocks of memory
surpassing a certain size, the memory manager will allocate those
separately. Those two modes of operation are shown as events of
different colors.
The second row displays the actual usage of the allocated memory.
This is the amount of JavaScript heap the application has actually
requested.
\li Qt 5.4
\li Qt Quick 2
\li Yes
\row
\li \gui Painting
\li Displays the time spent painting the scene for each frame.
\li Qt 4.7.4
\li Qt Quick 1
\li No
\row
\li \gui Animations
\li Displays the amount of animations that are active and the frame
rate that they are running at.
Information about render thread animations is displayed for
applications that are built with Qt 5.3 or later. Render thread
animations are shown in a separate row then.
\li Qt 5.0 (Qt 5.3)
\li Qt Quick 2
\li No
\row
\li \gui Compiling
\li Displays the time spent compiling the QML files.
\li Qt 4.7.4
\li Qt Quick 1 or Qt Quick 2
\li No
\row
\li \gui Creating
\li Displays the time spent creating the elements in the scene. In Qt
Quick 2, creation of elements takes place in two stages. The first
stage is for the creation of the data structures, including child
elements. The second stage represents the completion callbacks. Not
all elements trigger completion callbacks, though. The stages are
shown as separate events in the timeline.
For Qt Quick 2 applications compiled with versions of Qt before
5.2.1 only the creation of top-level elements is shown, as single
events.
\li Qt 4.7.4 (Qt 5.2.1)
\li Qt Quick 1 or Qt Quick 2
\li No
\row
\li \gui Binding
\li Displays the time when a binding is evaluated and how long the
evaluation takes.
\li Qt 4.7.4
\li Qt Quick 1 or Qt Quick 2
\li No
\row
\li \gui {Handling Signal}
\li Displays the time when a signal is handled and how long the
handling takes.
\li Qt 4.7.4
\li Qt Quick 1 or Qt Quick 2
\li No
\row
\li \gui JavaScript
\li Displays the time spent executing the actual JavaScript behind
bindings and signal handlers. It lists all the JavaScript functions
you may be using to evaluate bindings or handle signals.
\li Qt 5.3
\li Qt Quick 2
\li No
\endtable
\section1 Viewing Events
@@ -221,16 +296,21 @@
To copy the contents of one view or row to the clipboard, select
\gui {Copy Table} or \gui {Copy Row} in the context menu.
JavaScript events are shown in the \gui Events view only for applications
that use Qt Quick 2 and are compiled with Qt 5.3 or later. For applications
that use Qt Quick 2 and are built with Qt 5.0 or 5.1, you can view
information about JavaScript events in the separate \gui JavaScript view.
\section2 Viewing More Data
The QML JavaScript engine optimizes trivial bindings. The QML Profiler
does not receive information about optimized bindings, and
therefore, it displays the text \gui {<bytecode>} and the message
may not receive all information about optimized bindings, and therefore,
it may display the text \gui {<bytecode>} and the message
\gui {Source code not available} in the \gui Callers and \gui {Callees}
panes.
To inspect the optimized bindings, turn off the QML optimizer by setting the
environment variable QML_DISABLE_OPTIMIZER to 1. To set the environment
To inspect the optimized bindings, turn off the QML optimizer by setting
the environment variable QML_DISABLE_OPTIMIZER to 1. To set the environment
variable for the current project in the project settings:
\list 1

View File

@@ -39,11 +39,11 @@
\row
\li Bazaar
\li \l{http://bazaar.canonical.com/}
\li \QC 2.2 and later
\li
\row
\li ClearCase
\li \l{http://www-01.ibm.com/software/awdtools/clearcase/}
\li \QC 2.6 and later
\li
\row
\li CVS
\li \l{http://www.cvshome.org}
@@ -52,10 +52,12 @@
\li Git
\li \l{http://git-scm.com/}
\li Git version 1.7.2, or later
Gerrit version 2.6, or later
\row
\li Mercurial
\li \l{http://mercurial.selenic.com/}
\li \QC 2.0 and later
\li
\row
\li Perforce
\li \l{http://www.perforce.com}
@@ -399,8 +401,7 @@
for Windows, Linux and Mac.
You can use the \l{http://code.google.com/p/gerrit/}{Gerrit} code review
tool for projects that use Git. You can apply and check out changes from
Gerrit in \QC 2.6 and later.
tool for projects that use Git.
\section3 Working with the Current File

View File

@@ -107,7 +107,7 @@
\l{Positioning with Bindings}
{Property binding} is a declarative way of specifying the value of a property.
Binding allows a property value to be expressed as an JavaScript expression
Binding allows a property value to be expressed as a JavaScript expression
that defines the value relative to other property values or data accessible
in the application. The property value is automatically kept up to date if
the other properties or data values change.
@@ -126,7 +126,6 @@
\QMLD cannot show bindings and using them might have a negative impact on
performance, so consider setting anchors and margins for items, instead.
For example, instead of setting \c {parent.width} for an item, you could
anchor the item to its sibling items on the left and the right.

View File

@@ -1,8 +1,8 @@
!isEmpty(QTCREATOR_PRI_INCLUDED):error("qtcreator.pri already included")
QTCREATOR_PRI_INCLUDED = 1
QTCREATOR_VERSION = 3.1.81
QTCREATOR_COMPAT_VERSION = 3.1.81
QTCREATOR_VERSION = 3.1.82
QTCREATOR_COMPAT_VERSION = 3.1.82
BINARY_ARTIFACTS_BRANCH = master
# enable c++11

View File

@@ -4,11 +4,11 @@ Project {
property bool withAutotests: qbs.buildVariant === "debug"
property string ide_version_major: '3'
property string ide_version_minor: '1'
property string ide_version_release: '81'
property string ide_version_release: '82'
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.' + ide_version_release
property string ide_compat_version_major: '3'
property string ide_compat_version_minor: '1'
property string ide_compat_version_release: '81'
property string ide_compat_version_release: '82'
property string qtcreator_compat_version: ide_compat_version_major + '.' + ide_compat_version_minor + '.' + ide_compat_version_release
property path ide_source_tree: path
property string ide_app_path: qbs.targetOS.contains("osx") ? "" : "bin"

View File

@@ -1091,7 +1091,7 @@ static QObject *createDummyWindow(QQmlContext *context, const QUrl &sourceUrl)
QQmlComponent component(context->engine());
QByteArray dummyWindow;
dummyWindow.append("import QtQuick 2.0\n");
dummyWindow.append("Item {\n");
dummyWindow.append("Rectangle {\n");
dummyWindow.append("property string title\n");
dummyWindow.append("}\n");

View File

@@ -71,8 +71,10 @@ void QmlPropertyChangesNodeInstance::setPropertyVariant(const PropertyName &name
changesObject()->changeValue(name, value);
QObject *targetObject = changesObject()->object();
if (targetObject && nodeInstanceServer()->activeStateInstance().isWrappingThisObject(changesObject()->state())) {
ServerNodeInstance targetInstance = nodeInstanceServer()->instanceForObject(targetObject);
targetInstance.setPropertyVariant(name, value);
if (nodeInstanceServer()->hasInstanceForObject(targetObject)) {
ServerNodeInstance targetInstance = nodeInstanceServer()->instanceForObject(targetObject);
targetInstance.setPropertyVariant(name, value);
}
}
}
}

View File

@@ -64,12 +64,13 @@ QmlStateNodeInstance::Pointer
void QmlStateNodeInstance::activateState()
{
if (stateGroup()) {
if (!isStateActive()) {
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
stateGroup()->setState(property("name").toString());
}
if (stateGroup()
&& !isStateActive()
&& nodeInstanceServer()->hasInstanceForObject(object())) {
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
stateGroup()->setState(property("name").toString());
}
}
void QmlStateNodeInstance::deactivateState()

View File

@@ -199,9 +199,11 @@ void Qt5InformationNodeInstanceServer::collectItemChangesAndSendChangeCommands()
void Qt5InformationNodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
{
foreach (const ReparentContainer &container, command.reparentInstances()) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
m_parentChangedSet.insert(instance);
if (hasInstanceForId(container.instanceId())) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
m_parentChangedSet.insert(instance);
}
}
}
@@ -222,9 +224,11 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
QList<ServerNodeInstance> instanceList;
foreach (const InstanceContainer &container, command.instances()) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
if (hasInstanceForId(container.instanceId())) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
}
}
}
@@ -269,9 +273,11 @@ void Qt5InformationNodeInstanceServer::completeComponent(const CompleteComponent
QList<ServerNodeInstance> instanceList;
foreach (qint32 instanceId, command.instances()) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
if (hasInstanceForId(instanceId)) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
}
}
}

View File

@@ -42,6 +42,8 @@ namespace QmlDesigner {
Qt5PreviewNodeInstanceServer::Qt5PreviewNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
Qt5NodeInstanceServer(nodeInstanceClient)
{
setSlowRenderTimerInterval(100000000);
setRenderTimerInterval(100);
}
void Qt5PreviewNodeInstanceServer::createScene(const CreateSceneCommand &command)

View File

@@ -132,9 +132,11 @@ void Qt5RenderNodeInstanceServer::createScene(const CreateSceneCommand &command)
QList<ServerNodeInstance> instanceList;
foreach (const InstanceContainer &container, command.instances()) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
if (hasInstanceForId(container.instanceId())) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
}
}
}
@@ -154,10 +156,12 @@ void Qt5RenderNodeInstanceServer::completeComponent(const CompleteComponentComma
QList<ServerNodeInstance> instanceList;
foreach (qint32 instanceId, command.instances()) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
m_dirtyInstanceSet.insert(instance);
if (hasInstanceForId(instanceId)) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
m_dirtyInstanceSet.insert(instance);
}
}
}

View File

@@ -190,9 +190,11 @@ void Qt5TestNodeInstanceServer::removeProperties(const RemovePropertiesCommand &
void Qt5TestNodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
{
foreach (const ReparentContainer &container, command.reparentInstances()) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instance.reparent(instanceForId(container.oldParentInstanceId()), container.oldParentProperty(), instanceForId(container.newParentInstanceId()), container.newParentProperty());
if (hasInstanceForId(container.instanceId())) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instance.reparent(instanceForId(container.oldParentInstanceId()), container.oldParentProperty(), instanceForId(container.newParentInstanceId()), container.newParentProperty());
}
}
}

View File

@@ -140,16 +140,18 @@ QTransform GraphicsObjectNodeInstance::transform() const
if (!nodeInstanceServer()->hasInstanceForObject(object()))
return sceneTransform();
ServerNodeInstance nodeInstanceParent = nodeInstanceServer()->instanceForObject(object()).parent();
if (nodeInstanceServer()->hasInstanceForObject(object())) {
ServerNodeInstance nodeInstanceParent = nodeInstanceServer()->instanceForObject(object()).parent();
if (!nodeInstanceParent.isValid())
return sceneTransform();
if (!nodeInstanceParent.isValid())
return sceneTransform();
QGraphicsObject *graphicsObjectParent = qobject_cast<QGraphicsObject*>(nodeInstanceParent.internalObject());
if (graphicsObjectParent)
return graphicsObject()->itemTransform(graphicsObjectParent);
else
return sceneTransform();
QGraphicsObject *graphicsObjectParent = qobject_cast<QGraphicsObject*>(nodeInstanceParent.internalObject());
if (graphicsObjectParent)
return graphicsObject()->itemTransform(graphicsObjectParent);
}
return sceneTransform();
}
QTransform GraphicsObjectNodeInstance::customTransform() const

View File

@@ -71,8 +71,10 @@ void QmlPropertyChangesNodeInstance::setPropertyVariant(const PropertyName &name
changesObject()->changeValue(name, value);
QObject *targetObject = changesObject()->object();
if (targetObject && nodeInstanceServer()->activeStateInstance().isWrappingThisObject(changesObject()->state())) {
ServerNodeInstance targetInstance = nodeInstanceServer()->instanceForObject(targetObject);
targetInstance.setPropertyVariant(name, value);
if (nodeInstanceServer()->hasInstanceForObject(targetObject)) {
ServerNodeInstance targetInstance = nodeInstanceServer()->instanceForObject(targetObject);
targetInstance.setPropertyVariant(name, value);
}
}
}
}

View File

@@ -64,11 +64,11 @@ QmlStateNodeInstance::Pointer
void QmlStateNodeInstance::activateState()
{
if (stateGroup()) {
if (!isStateActive()) {
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
stateGroup()->setState(property("name").toString());
}
if (stateGroup()
&& !isStateActive()
&& nodeInstanceServer()->hasInstanceForObject(object())) {
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
stateGroup()->setState(property("name").toString());
}
}

View File

@@ -198,9 +198,11 @@ void Qt4InformationNodeInstanceServer::collectItemChangesAndSendChangeCommands()
void Qt4InformationNodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
{
foreach(const ReparentContainer &container, command.reparentInstances()) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
m_parentChangedSet.insert(instance);
if (hasInstanceForId(container.instanceId())) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
m_parentChangedSet.insert(instance);
}
}
}
@@ -221,9 +223,11 @@ void Qt4InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
QList<ServerNodeInstance> instanceList;
foreach(const InstanceContainer &container, command.instances()) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
if (hasInstanceForId(container.instanceId())) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
}
}
}
@@ -263,9 +267,11 @@ void Qt4InformationNodeInstanceServer::completeComponent(const CompleteComponent
QList<ServerNodeInstance> instanceList;
foreach(qint32 instanceId, command.instances()) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
if (hasInstanceForId(instanceId)) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
}
}
}

View File

@@ -154,9 +154,11 @@ void Qt4RenderNodeInstanceServer::createScene(const CreateSceneCommand &command)
QList<ServerNodeInstance> instanceList;
foreach(const InstanceContainer &container, command.instances()) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
if (hasInstanceForId(container.instanceId())) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
instanceList.append(instance);
}
}
}
@@ -176,9 +178,11 @@ void Qt4RenderNodeInstanceServer::completeComponent(const CompleteComponentComma
QList<ServerNodeInstance> instanceList;
foreach(qint32 instanceId, command.instances()) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
if (hasInstanceForId(instanceId)) {
ServerNodeInstance instance = instanceForId(instanceId);
if (instance.isValid()) {
instanceList.append(instance);
}
}
}

View File

@@ -61,9 +61,11 @@ Rectangle {
anchors.leftMargin: styleConstants.cellHorizontalMargin
anchors.right: parent.right
anchors.rightMargin: styleConstants.cellHorizontalMargin
anchors.bottom: parent.bottom
anchors.bottomMargin: styleConstants.cellHorizontalMargin
verticalAlignment: "AlignVCenter"
horizontalAlignment: "AlignHCenter"
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
text: itemName // to be set by model
color: "#FFFFFF"
renderType: Text.NativeRendering

View File

@@ -72,11 +72,11 @@ ScrollView {
property color lighterBackgroundColor: "#5f5f5f"
property int textWidth: 55
property int textHeight: 30
property int textHeight: 26
property int cellHorizontalMargin: 5
property int cellVerticalSpacing: 3
property int cellVerticalMargin: 3
property int cellVerticalMargin: 7
// the following depend on the actual shape of the item delegate
property int cellWidth: textWidth + 2 * cellHorizontalMargin
@@ -104,6 +104,9 @@ ScrollView {
width: itemsView.viewport.width
caption: sectionName // to be set by model
visible: sectionVisible
topPadding: 2
leftPadding: 2
rightPadding: 1
Grid {
id: itemGrid

View File

@@ -35,6 +35,9 @@ Item {
id: section
property alias caption: label.text
property int leftPadding: 8
property int topPadding: 4
property int rightPadding: 0
clip: true
@@ -93,16 +96,19 @@ Item {
}
}
default property alias __content: row.data
default property alias __content: row.children
readonly property alias contentItem: row
implicitHeight: Math.round(row.height + header.height + 8)
Row {
width: parent.width
x: 8
y: header.height + 4
anchors.left: parent.left
anchors.leftMargin: leftPadding
anchors.right: parent.right
anchors.rightMargin: rightPadding
anchors.top: header.bottom
anchors.topMargin: topPadding
id: row
Behavior on opacity { NumberAnimation{easing.type: Easing.Linear ; duration: 80} }
}

View File

@@ -41,36 +41,19 @@ Rectangle {
property int delegateStateImageSize
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.lighter(gradiantBaseColor, 1.1) }
GradientStop { position: 0.2; color: Qt.lighter(gradiantBaseColor, 1.2) }
GradientStop { position: 0.3; color: Qt.lighter(gradiantBaseColor, 1.1) }
GradientStop { position: 1.0; color: gradiantBaseColor }
GradientStop { position: 0.0; color: Qt.lighter(gradiantBaseColor, 1.5) }
GradientStop { position: 0.1; color: Qt.lighter(gradiantBaseColor, 1) }
GradientStop { position: 0.8; color: gradiantBaseColor }
GradientStop { position: 1.0; color: Qt.darker(gradiantBaseColor) }
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
acceptedButtons: Qt.LeftButton
onClicked: {
if (mouse.button === Qt.LeftButton) {
focus = true
root.currentStateInternalId = internalNodeId
} else if (mouse.button === Qt.RightButton) {
contextMenu.popup()
}
}
Menu {
id: contextMenu
MenuItem {
text: root.expanded ? qsTr("Collapse") : qsTr("Expand")
onTriggered: {
root.expanded = ! root.expanded
}
}
focus = true
root.currentStateInternalId = internalNodeId
}
}

View File

@@ -35,7 +35,7 @@ import "../common"
FocusScope {
id: root
height: expanded ? 132 : 32
height: expanded ? 136 : 32
signal createNewState
signal deleteState(int internalNodeId)
signal duplicateCurrentState
@@ -44,7 +44,7 @@ FocusScope {
property int delegateWidth: stateImageSize + 10
property int padding: 2
property int delegateHeight: root.height - padding * 2
property int innerSpacing: 2
property int innerSpacing: -1
property int currentStateInternalId : 0
property bool expanded: true
@@ -63,31 +63,41 @@ FocusScope {
anchors.fill: parent
color: "#4f4f4f"
}
MouseArea {
anchors.fill: parent
onClicked: focus = true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button === Qt.LeftButton)
focus = true
else if (mouse.button === Qt.RightButton)
contextMenu.popup()
}
Menu {
id: contextMenu
MenuItem {
text: root.expanded ? qsTr("Collapse") : qsTr("Expand")
onTriggered: {
root.expanded = !root.expanded
}
}
}
}
Item {
id: addStateItem
property int buttonLeftSpacing: innerSpacing
property int buttonLeftSpacing: 0
anchors.right: parent.right
width: delegateHeight / 2 + buttonLeftSpacing
height: delegateHeight
Button {
style: ButtonStyle {
background: Rectangle {
implicitWidth: 100
implicitHeight: 25
color: control.hovered ? "#6f6f6f" : "#4f4f4f"
border.color: "black"
}
}
id: addStateButton
visible: canAddNewStates
@@ -130,16 +140,6 @@ FocusScope {
delegateStateImageSource: stateImageSource
delegateStateImageSize: stateImageSize
}
Rectangle {
/* Rectangle at the bottom using the highlight color */
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 1
anchors.rightMargin: 1
height: 4
color: Qt.darker(highlightColor, 1.2)
}
}
}
}

View File

@@ -4455,6 +4455,9 @@ public:
ExceptionSpecificationAST *exception_specification;
TrailingReturnTypeAST *trailing_return_type;
public: // annotations
Function *symbol;
public:
LambdaDeclaratorAST()
: lparen_token(0)

View File

@@ -1087,11 +1087,10 @@ bool Bind::visit(LambdaDeclaratorAST *ast)
return false;
}
void Bind::lambdaDeclarator(LambdaDeclaratorAST *ast)
Function *Bind::lambdaDeclarator(LambdaDeclaratorAST *ast)
{
if (! ast)
return;
return 0;
Function *fun = control()->newFunction(0, 0);
fun->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
@@ -1099,6 +1098,7 @@ void Bind::lambdaDeclarator(LambdaDeclaratorAST *ast)
if (ast->trailing_return_type)
_type = this->trailingReturnType(ast->trailing_return_type, _type);
fun->setReturnType(_type);
ast->symbol = fun;
// unsigned lparen_token = ast->lparen_token;
FullySpecifiedType type;
@@ -1108,7 +1108,8 @@ void Bind::lambdaDeclarator(LambdaDeclaratorAST *ast)
type = this->specifier(it->value, type);
}
// unsigned mutable_token = ast->mutable_token;
type = this->exceptionSpecification(ast->exception_specification, type);
_type = this->exceptionSpecification(ast->exception_specification, type);
return fun;
}
bool Bind::visit(TrailingReturnTypeAST *ast)
@@ -1780,8 +1781,15 @@ bool Bind::visit(ObjCSelectorExpressionAST *ast)
bool Bind::visit(LambdaExpressionAST *ast)
{
this->lambdaIntroducer(ast->lambda_introducer);
this->lambdaDeclarator(ast->lambda_declarator);
this->statement(ast->statement);
if (Function *function = this->lambdaDeclarator(ast->lambda_declarator)) {
_scope->addMember(function);
Scope *previousScope = switchScope(function);
this->statement(ast->statement);
(void) switchScope(previousScope);
} else {
this->statement(ast->statement);
}
return false;
}

View File

@@ -103,7 +103,7 @@ protected:
void lambdaIntroducer(LambdaIntroducerAST *ast);
void lambdaCapture(LambdaCaptureAST *ast);
void capture(CaptureAST *ast);
void lambdaDeclarator(LambdaDeclaratorAST *ast);
Function *lambdaDeclarator(LambdaDeclaratorAST *ast);
FullySpecifiedType trailingReturnType(TrailingReturnTypeAST *ast, const FullySpecifiedType &init);
const StringLiteral *asStringLiteral(unsigned firstToken, unsigned lastToken);

View File

@@ -164,7 +164,7 @@ void TranslationUnit::tokenize()
_Lrecognize:
if (tk.is(T_POUND) && tk.newline()) {
unsigned offset = tk.byteOffset;
const unsigned utf16CharOffset = tk.utf16charOffset;
lex(&tk);
if (! tk.newline() && tk.is(T_IDENTIFIER) && tk.identifier == expansionId) {
@@ -237,7 +237,7 @@ void TranslationUnit::tokenize()
if (! tk.newline() && tk.is(T_STRING_LITERAL)) {
const StringLiteral *fileName =
control()->stringLiteral(tk.string->chars(), tk.string->size());
pushPreprocessorLine(offset, line, fileName);
pushPreprocessorLine(utf16CharOffset, line, fileName);
lex(&tk);
}
}
@@ -343,10 +343,10 @@ bool TranslationUnit::parse(ParseMode mode)
void TranslationUnit::pushLineOffset(unsigned offset)
{ _lineOffsets.push_back(offset); }
void TranslationUnit::pushPreprocessorLine(unsigned offset,
void TranslationUnit::pushPreprocessorLine(unsigned utf16charOffset,
unsigned line,
const StringLiteral *fileName)
{ _ppLines.push_back(PPLine(offset, line, fileName)); }
{ _ppLines.push_back(PPLine(utf16charOffset, line, fileName)); }
unsigned TranslationUnit::findLineNumber(unsigned utf16charOffset) const
{
@@ -359,10 +359,10 @@ unsigned TranslationUnit::findLineNumber(unsigned utf16charOffset) const
return it - _lineOffsets.begin();
}
TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned offset) const
TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned utf16charOffset) const
{
std::vector<PPLine>::const_iterator it =
std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(offset));
std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(utf16charOffset));
if (it != _ppLines.begin())
--it;
@@ -419,7 +419,7 @@ void TranslationUnit::getPosition(unsigned utf16charOffset,
// Adjust the line in regards to the preprocessing markers.
const PPLine ppLine = findPreprocessorLine(utf16charOffset);
lineNumber -= findLineNumber(ppLine.offset) + 1;
lineNumber -= findLineNumber(ppLine.utf16charOffset) + 1;
lineNumber += ppLine.line;
file = ppLine.fileName;

View File

@@ -138,7 +138,7 @@ public:
const StringLiteral **fileName = 0) const;
void pushLineOffset(unsigned offset);
void pushPreprocessorLine(unsigned offset,
void pushPreprocessorLine(unsigned utf16charOffset,
unsigned line,
const StringLiteral *fileName);
@@ -151,30 +151,30 @@ public:
private:
struct PPLine {
unsigned offset;
unsigned utf16charOffset;
unsigned line;
const StringLiteral *fileName;
PPLine(unsigned offset = 0,
PPLine(unsigned utf16charOffset = 0,
unsigned line = 0,
const StringLiteral *fileName = 0)
: offset(offset), line(line), fileName(fileName)
: utf16charOffset(utf16charOffset), line(line), fileName(fileName)
{ }
bool operator == (const PPLine &other) const
{ return offset == other.offset; }
{ return utf16charOffset == other.utf16charOffset; }
bool operator != (const PPLine &other) const
{ return offset != other.offset; }
{ return utf16charOffset != other.utf16charOffset; }
bool operator < (const PPLine &other) const
{ return offset < other.offset; }
{ return utf16charOffset < other.utf16charOffset; }
};
void releaseTokensAndComments();
unsigned findLineNumber(unsigned utf16charOffset) const;
unsigned findColumnNumber(unsigned utf16CharOffset, unsigned lineNumber) const;
PPLine findPreprocessorLine(unsigned offset) const;
PPLine findPreprocessorLine(unsigned utf16charOffset) const;
void showErrorLine(unsigned index, unsigned column, FILE *out);
static const Token nullToken;

View File

@@ -1082,9 +1082,9 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
const unsigned argumentCountOfSpecialization
= templateSpecialization->templateParameterCount();
Subst subst(_control.data());
if (_factory->expandTemplates()) {
Clone cloner(_control.data());
Subst subst(_control.data());
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) {
const TypenameArgument *tParam
= templateSpecialization->templateParameterAt(i)->asTypenameArgument();
@@ -1149,6 +1149,13 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
}
}
}
if (!baseBinding && subst.contains(baseName)) {
const FullySpecifiedType &fullType = subst[baseName];
if (fullType.isValid()) {
if (NamedType *namedType = fullType.type()->asNamedType())
baseBinding = lookupType(namedType->name());
}
}
} else {
SubstitutionMap map;
for (unsigned i = 0;

View File

@@ -265,6 +265,16 @@ QRegExp PluginSpec::platformSpecification() const
return d->platformSpecification;
}
bool PluginSpec::isAvailableForHostPlatform() const
{
return d->platformSpecification.isEmpty() || d->platformSpecification.exactMatch(PluginManager::platformName());
}
bool PluginSpec::isRequired() const
{
return d->required;
}
/*!
Returns whether the plugin has its experimental flag set.
*/
@@ -307,7 +317,7 @@ bool PluginSpec::isEffectivelyEnabled() const
|| d->forceDisabled) {
return false;
}
return d->platformSpecification.isEmpty() || d->platformSpecification.exactMatch(PluginManager::platformName());
return isAvailableForHostPlatform();
}
/*!
@@ -460,6 +470,7 @@ namespace {
const char PLUGIN_NAME[] = "name";
const char PLUGIN_VERSION[] = "version";
const char PLUGIN_COMPATVERSION[] = "compatVersion";
const char PLUGIN_REQUIRED[] = "required";
const char PLUGIN_EXPERIMENTAL[] = "experimental";
const char PLUGIN_DISABLED_BY_DEFAULT[] = "disabledByDefault";
const char VENDOR[] = "vendor";
@@ -485,17 +496,17 @@ namespace {
\internal
*/
PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec)
:
experimental(false),
disabledByDefault(false),
enabledInSettings(true),
disabledIndirectly(false),
forceEnabled(false),
forceDisabled(false),
plugin(0),
state(PluginSpec::Invalid),
hasError(false),
q(spec)
: required(false),
experimental(false),
disabledByDefault(false),
enabledInSettings(true),
disabledIndirectly(false),
forceEnabled(false),
forceDisabled(false),
plugin(0),
state(PluginSpec::Invalid),
hasError(false),
q(spec)
{
}
@@ -642,8 +653,9 @@ void PluginSpecPrivate::readPluginSpec(QXmlStreamReader &reader)
} else if (compatVersion.isEmpty()) {
compatVersion = version;
}
disabledByDefault = readBooleanValue(reader, PLUGIN_DISABLED_BY_DEFAULT);
required = readBooleanValue(reader, PLUGIN_REQUIRED);
experimental = readBooleanValue(reader, PLUGIN_EXPERIMENTAL);
disabledByDefault = readBooleanValue(reader, PLUGIN_DISABLED_BY_DEFAULT);
if (reader.hasError())
return;
if (experimental)

View File

@@ -92,6 +92,8 @@ public:
QString url() const;
QString category() const;
QRegExp platformSpecification() const;
bool isAvailableForHostPlatform() const;
bool isRequired() const;
bool isExperimental() const;
bool isDisabledByDefault() const;
bool isEnabledInSettings() const;

View File

@@ -65,6 +65,7 @@ public:
QString name;
QString version;
QString compatVersion;
bool required;
bool experimental;
bool disabledByDefault;
QString vendor;

View File

@@ -108,10 +108,6 @@ PluginView::PluginView(QWidget *parent)
m_errorIcon = QIcon(QLatin1String(":/extensionsystem/images/error.png"));
m_notLoadedIcon = QIcon(QLatin1String(":/extensionsystem/images/notloaded.png"));
// cannot disable these
m_whitelist << QString::fromLatin1("Core") << QString::fromLatin1("Locator")
<< QString::fromLatin1("Find") << QString::fromLatin1("TextEditor");
connect(PluginManager::instance(), SIGNAL(pluginsChanged()), this, SLOT(updateList()));
connect(m_categoryWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
this, SLOT(selectPlugin(QTreeWidgetItem*)));
@@ -234,15 +230,19 @@ int PluginView::parsePluginSpecs(QTreeWidgetItem *parentItem, Qt::CheckState &gr
++checkedCount;
}
if (!m_whitelist.contains(spec->name())) {
pluginItem->setData(C_LOAD, Qt::CheckStateRole, state);
} else {
if (!spec->isAvailableForHostPlatform()) {
pluginItem->setData(C_LOAD, Qt::CheckStateRole, Qt::Unchecked);
pluginItem->setFlags(Qt::ItemIsSelectable);
pluginItem->setToolTip(C_LOAD, tr("Plugin is not available on this platform."));
} else if (spec->isRequired()){
pluginItem->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
pluginItem->setFlags(Qt::ItemIsSelectable);
pluginItem->setToolTip(C_LOAD, tr("Plugin is required."));
} else {
pluginItem->setData(C_LOAD, Qt::CheckStateRole, state);
pluginItem->setToolTip(C_LOAD, tr("Load on startup"));
}
pluginItem->setToolTip(C_LOAD, tr("Load on Startup"));
m_specToItem.insert(spec, pluginItem);
if (parentItem)
@@ -336,13 +336,10 @@ void PluginView::updatePluginSettings(QTreeWidgetItem *item, int column)
PluginSpec *spec = collection->plugins().at(i);
QTreeWidgetItem *child = m_specToItem.value(spec);
if (!m_whitelist.contains(spec->name())) {
if (spec->isAvailableForHostPlatform() && !spec->isRequired()) {
spec->setEnabled(loadOnStartup);
Qt::CheckState state = (loadOnStartup ? Qt::Checked : Qt::Unchecked);
child->setData(C_LOAD, Qt::CheckStateRole, state);
} else {
child->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
child->setFlags(Qt::ItemIsSelectable);
}
}
updatePluginDependencies();
@@ -357,7 +354,7 @@ void PluginView::updatePluginDependencies()
{
foreach (PluginSpec *spec, PluginManager::loadQueue()) {
bool disableIndirectly = false;
if (m_whitelist.contains(spec->name()))
if (spec->isRequired())
continue;
QHashIterator<PluginDependency, PluginSpec *> it(spec->dependencySpecs());
@@ -372,7 +369,7 @@ void PluginView::updatePluginDependencies()
}
}
QTreeWidgetItem *childItem = m_specToItem.value(spec);
childItem->setDisabled(disableIndirectly);
childItem->setDisabled(disableIndirectly || !spec->isAvailableForHostPlatform());
if (disableIndirectly == spec->isDisabledIndirectly())
continue;

View File

@@ -79,7 +79,6 @@ private:
QList<QTreeWidgetItem*> m_items;
QHash<PluginSpec*, QTreeWidgetItem*> m_specToItem;
QStringList m_whitelist;
QIcon m_okIcon;
QIcon m_errorIcon;
QIcon m_notLoadedIcon;

View File

@@ -35,9 +35,11 @@
#include <QTextDocument>
#include <QTextBlock>
namespace QmlJS {
namespace {
Q_LOGGING_CATEGORY(formatterLog, "qtc.qmljs.formatter")
}
namespace QmlJS {
CodeFormatter::BlockData::BlockData()
: m_indentDepth(0)

View File

@@ -38,6 +38,7 @@
#include <QCryptographicHash>
#include <QDir>
#include <QFileInfo>
#include <algorithm>
@@ -525,7 +526,7 @@ void Snapshot::insert(const Document::Ptr &document, bool allowInvalid)
cImport.importId = document->importId();
cImport.language = document->language();
cImport.possibleExports << Export(ImportKey(ImportType::File, fileName),
QString(), true);
QString(), true, QFileInfo(fileName).baseName());
cImport.fingerprint = document->fingerprint();
_dependencies.addCoreImport(cImport);
}
@@ -554,15 +555,59 @@ void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info)
}
QStringList splitPath = path.split(QLatin1Char('/'));
QRegExp vNr(QLatin1String("^(.+)\\.([0-9]+)(?:\\.([0-9]+))?$"));
QRegExp safeName(QLatin1String("^[a-zA-Z_][[a-zA-Z0-9_]*$"));
foreach (const ImportKey &importKey, packages) {
QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size()))
.join(QLatin1String("/"));
cImport.possibleExports << Export(importKey, requiredPath, true);
if (importKey.splitPath.size() == 1 && importKey.splitPath.at(0).isEmpty()) {
// relocatable
QStringList myPath = splitPath;
if (vNr.indexIn(myPath.last()) == 0) {
myPath.last() = vNr.cap(1);
}
for (int iPath = myPath.size(); iPath != 0; ) {
--iPath;
if (safeName.indexIn(myPath.at(iPath)) != 0)
break;
ImportKey iKey(ImportType::Library, QStringList(myPath.mid(iPath)).join(QLatin1String(".")),
importKey.majorVersion, importKey.minorVersion);
cImport.possibleExports.append(Export(iKey, QStringList(myPath.mid(0, iPath))
.join(QLatin1String("/")), true));
}
} else {
QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size()))
.join(QLatin1String("/"));
cImport.possibleExports << Export(importKey, requiredPath, true);
}
}
if (cImport.possibleExports.isEmpty()) {
QRegExp vNr(QLatin1String("^(.+)\\.([0-9]+)(?:\\.([0-9]+))?$"));
QRegExp safeName(QLatin1String("^[a-zA-Z_][[a-zA-Z0-9_]*$"));
int majorVersion = LanguageUtils::ComponentVersion::NoVersion;
int minorVersion = LanguageUtils::ComponentVersion::NoVersion;
if (vNr.indexIn(splitPath.last()) == 0) {
splitPath.last() = vNr.cap(1);
bool ok;
majorVersion = vNr.cap(2).toInt(&ok);
if (!ok)
majorVersion = LanguageUtils::ComponentVersion::NoVersion;
minorVersion = vNr.cap(3).toInt(&ok);
if (vNr.cap(3).isEmpty() || !ok)
minorVersion = LanguageUtils::ComponentVersion::NoVersion;
}
for (int iPath = splitPath.size(); iPath != 0; ) {
--iPath;
if (safeName.indexIn(splitPath.at(iPath)) != 0)
break;
ImportKey iKey(ImportType::Library, QStringList(splitPath.mid(iPath)).join(QLatin1String(".")),
majorVersion, minorVersion);
cImport.possibleExports.append(Export(iKey, QStringList(splitPath.mid(0, iPath))
.join(QLatin1String("/")), true));
}
}
foreach (const QmlDirParser::Component &component, info.components()) {
foreach (const Export &e, cImport.possibleExports)
// renaming of type name not really represented here... fix?
_dependencies.addExport(component.fileName, e.exportName, e.pathRequired);
_dependencies.addExport(component.fileName, e.exportName, e.pathRequired, e.typeName);
}
cImport.fingerprint = info.fingerprint();
_dependencies.addCoreImport(cImport);

View File

@@ -43,9 +43,11 @@ enum {
debug = false
};
namespace QmlJS {
namespace {
Q_LOGGING_CATEGORY(iconsLog, "qtc.qmljs.icons")
}
namespace QmlJS {
Icons *Icons::m_instance = 0;

View File

@@ -38,9 +38,11 @@
#include <algorithm>
namespace QmlJS {
namespace {
Q_LOGGING_CATEGORY(importsLog, "qtc.qmljs.imports")
}
namespace QmlJS {
ImportKind::Enum toImportKind(ImportType::Enum type)
{
@@ -471,12 +473,14 @@ bool operator <(const ImportKey &i1, const ImportKey &i2)
return i1.compare(i2) < 0;
}
const QString Export::LibraryTypeName = QLatin1String("%Library%");
Export::Export()
: intrinsic(false)
{ }
Export::Export(ImportKey exportName, QString pathRequired, bool intrinsic)
: exportName(exportName), pathRequired(pathRequired), intrinsic(intrinsic)
Export::Export(ImportKey exportName, QString pathRequired, bool intrinsic, const QString &typeName)
: exportName(exportName), pathRequired(pathRequired), typeName(typeName), intrinsic(intrinsic)
{ }
bool Export::visibleInVContext(const ViewerContext &vContext) const
@@ -488,7 +492,8 @@ bool operator ==(const Export &i1, const Export &i2)
{
return i1.exportName == i2.exportName
&& i1.pathRequired == i2.pathRequired
&& i1.intrinsic == i2.intrinsic;
&& i1.intrinsic == i2.intrinsic
&& i1.typeName == i2.typeName;
}
bool operator !=(const Export &i1, const Export &i2)
@@ -770,32 +775,32 @@ void ImportDependencies::removeImportCacheEntry(const ImportKey &importKey, cons
}
void ImportDependencies::addExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath)
const QString &requiredPath, const QString &typeName)
{
if (!m_coreImports.contains(importId)) {
CoreImport newImport(importId);
newImport.language = Language::AnyLanguage;
newImport.possibleExports.append(Export(importKey, requiredPath, false));
newImport.possibleExports.append(Export(importKey, requiredPath, false, typeName));
m_coreImports.insert(newImport.importId, newImport);
m_importCache[importKey].append(importId);
return;
}
CoreImport &importValue = m_coreImports[importId];
importValue.possibleExports.append(Export(importKey, requiredPath, false));
importValue.possibleExports.append(Export(importKey, requiredPath, false, typeName));
m_importCache[importKey].append(importId);
qCDebug(importsLog) << "added export "<< importKey.toString() << " for id " <<importId
<< " (" << requiredPath << ")";
}
void ImportDependencies::removeExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath)
const QString &requiredPath, const QString &typeName)
{
if (!m_coreImports.contains(importId)) {
qCWarning(importsLog) << "non existing core import for removeExport(" << importId << ", "
<< importKey.toString() << ")";
} else {
CoreImport &importValue = m_coreImports[importId];
if (!importValue.possibleExports.removeOne(Export(importKey, requiredPath, false))) {
if (!importValue.possibleExports.removeOne(Export(importKey, requiredPath, false, typeName))) {
qCWarning(importsLog) << "non existing export for removeExport(" << importId << ", "
<< importKey.toString() << ")";
}

View File

@@ -128,10 +128,13 @@ bool operator <(const ImportKey &i1, const ImportKey &i2);
class QMLJS_EXPORT Export
{
public:
static const QString LibraryTypeName;
Export();
Export(ImportKey exportName, QString pathRequired, bool intrinsic = false);
Export(ImportKey exportName, QString pathRequired, bool intrinsic = false,
const QString &typeName = LibraryTypeName);
ImportKey exportName;
QString pathRequired;
QString typeName;
bool intrinsic;
bool visibleInVContext(const ViewerContext &vContext) const;
};
@@ -205,9 +208,9 @@ public:
void removeCoreImport(const QString &importId);
void addExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath);
const QString &requiredPath, const QString &typeName = Export::LibraryTypeName);
void removeExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath);
const QString &requiredPath, const QString &typeName = Export::LibraryTypeName);
void iterateOnCoreImports(const ViewerContext &vContext,
std::function<bool(const CoreImport &)> const &iterF) const;

View File

@@ -749,6 +749,8 @@ static bool findNewQmlLibraryInPath(const QString &path,
const QString libraryPath = QFileInfo(qmldirFile).absolutePath();
newLibraries->insert(libraryPath);
modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser));
modelManager->loadPluginTypes(QFileInfo(libraryPath).canonicalFilePath(), libraryPath,
QString(), QString());
// scan the qml files in the library
foreach (const QmlDirParser::Component &component, qmldirParser.components()) {
@@ -1283,8 +1285,11 @@ ViewerContext ModelManagerInterface::completeVContext(const ViewerContext &vCtx,
{
ViewerContext res = vCtx;
if (vCtx.language == Language::Qml && !doc.isNull() &&
(doc->language() == Language::QmlQtQuick1 || doc->language() == Language::QmlQtQuick2))
if (!doc.isNull()
&& ((vCtx.language == Language::AnyLanguage && doc->language() != Language::NoLanguage)
|| (vCtx.language == Language::Qml
&& (doc->language() == Language::QmlQtQuick1
|| doc->language() == Language::QmlQtQuick2))))
res.language = doc->language();
ProjectInfo info;
if (!doc.isNull())
@@ -1362,7 +1367,7 @@ ViewerContext ModelManagerInterface::defaultVContext(Language::Enum language,
bool autoComplete) const
{
if (!doc.isNull()) {
if (language == Language::AnyLanguage)
if (language == Language::AnyLanguage && doc->language() != Language::NoLanguage)
language = doc->language();
else if (language == Language::Qml &&
(doc->language() == Language::QmlQtQuick1 || doc->language() == Language::QmlQtQuick2))
@@ -1373,6 +1378,7 @@ ViewerContext ModelManagerInterface::defaultVContext(Language::Enum language,
QMutexLocker locker(&m_mutex);
defaultCtx = m_defaultVContexts.value(language);
}
defaultCtx.language = language;
if (autoComplete)
return completeVContext(defaultCtx, doc);
else

View File

@@ -39,8 +39,11 @@
#include <QFile>
namespace QmlJS{
namespace {
Q_LOGGING_CATEGORY(simpleReaderLog, "qtc.qmljs.simpleReader")
}
namespace QmlJS{
QVariant SimpleReaderNode::property(const QString &name) const
{

View File

@@ -427,7 +427,10 @@ void AutotoolsProject::updateCppCodeModel()
foreach (const QString &file, m_files)
part->files << CppTools::ProjectFile(file, CppTools::ProjectFile::CXXSource);
part->includePaths += m_makefileParserThread->includePaths();
foreach (const QString &inc, m_makefileParserThread->includePaths()) {
part->headerPaths += CppTools::ProjectPart::HeaderPath(
inc, CppTools::ProjectPart::HeaderPath::IncludePath);
}
part->projectDefines += m_makefileParserThread->defines();
pinfo.appendProjectPart(part);

View File

@@ -1571,6 +1571,7 @@ void BinEditorWidget::updateContents()
m_oldData = m_data;
m_data.clear();
setSizes(baseAddress() + cursorPosition(), m_size, m_blockSize);
viewport()->update();
}
QPoint BinEditorWidget::offsetToPos(int offset) const

View File

@@ -54,9 +54,10 @@ void Bookmark::removedFromEditor()
void Bookmark::updateLineNumber(int line)
{
if (line != lineNumber())
if (line != lineNumber()) {
BaseTextMark::updateLineNumber(line);
m_manager->updateBookmark(this);
BaseTextMark::updateLineNumber(line);
}
}
void Bookmark::updateBlock(const QTextBlock &block)

View File

@@ -213,7 +213,8 @@ IAssistInterface *ClangCompletionAssistProvider::createAssistInterface(
QList<ProjectPart::Ptr> parts = modelManager->projectPart(fileName);
if (parts.isEmpty())
parts += modelManager->fallbackProjectPart();
QStringList includePaths, frameworkPaths, options;
ProjectPart::HeaderPaths headerPaths;
QStringList options;
PchInfo::Ptr pchInfo;
foreach (ProjectPart::Ptr part, parts) {
if (part.isNull())
@@ -222,15 +223,14 @@ IAssistInterface *ClangCompletionAssistProvider::createAssistInterface(
pchInfo = PchManager::instance()->pchInfo(part);
if (!pchInfo.isNull())
options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName()));
includePaths = part->includePaths;
frameworkPaths = part->frameworkPaths;
headerPaths = part->headerPaths;
break;
}
return new ClangCodeModel::ClangCompletionAssistInterface(
m_clangCompletionWrapper,
document, position, fileName, reason,
options, includePaths, frameworkPaths, pchInfo);
options, headerPaths, pchInfo);
}
// ------------------------
@@ -550,14 +550,12 @@ ClangCompletionAssistInterface::ClangCompletionAssistInterface(ClangCompleter::P
const QString &fileName,
AssistReason reason,
const QStringList &options,
const QStringList &includePaths,
const QStringList &frameworkPaths,
const QList<CppTools::ProjectPart::HeaderPath> &headerPaths,
const PchInfo::Ptr &pchInfo)
: DefaultAssistInterface(document, position, fileName, reason)
, m_clangWrapper(clangWrapper)
, m_options(options)
, m_includePaths(includePaths)
, m_frameworkPaths(frameworkPaths)
, m_headerPaths(headerPaths)
, m_savedPchPointer(pchInfo)
{
Q_ASSERT(!clangWrapper.isNull());
@@ -1138,29 +1136,22 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
}
// Make completion for all relevant includes
QStringList includePaths = m_interface->includePaths();
const QString &currentFilePath = QFileInfo(m_interface->fileName()).path();
if (!includePaths.contains(currentFilePath))
includePaths.append(currentFilePath);
ProjectPart::HeaderPaths headerPaths = m_interface->headerPaths();
const ProjectPart::HeaderPath currentFilePath(QFileInfo(m_interface->fileName()).path(),
ProjectPart::HeaderPath::IncludePath);
if (!headerPaths.contains(currentFilePath))
headerPaths.append(currentFilePath);
const Core::MimeType mimeType = Core::MimeDatabase::findByType(QLatin1String("text/x-c++hdr"));
const QStringList suffixes = mimeType.suffixes();
foreach (const QString &includePath, includePaths) {
QString realPath = includePath;
foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) {
QString realPath = headerPath.path;
if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/');
realPath += directoryPrefix;
}
completeIncludePath(realPath, suffixes);
}
foreach (const QString &frameworkPath, m_interface->frameworkPaths()) {
QString realPath = frameworkPath;
if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/');
realPath += directoryPrefix;
realPath += QLatin1String(".framework/Headers");
if (headerPath.isFrameworkPath())
realPath += QLatin1String(".framework/Headers");
}
completeIncludePath(realPath, suffixes);
}

View File

@@ -35,6 +35,7 @@
#include <cplusplus/Icons.h>
#include <cpptools/cppcompletionassistprovider.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <texteditor/codeassist/basicproposalitem.h>
#include <texteditor/codeassist/completionassistprovider.h>
@@ -76,8 +77,7 @@ public:
const QString &fileName,
TextEditor::AssistReason reason,
const QStringList &options,
const QStringList &includePaths,
const QStringList &frameworkPaths,
const QList<CppTools::ProjectPart::HeaderPath> &headerPaths,
const Internal::PchInfo::Ptr &pchInfo);
ClangCodeModel::ClangCompleter::Ptr clangWrapper() const
@@ -91,16 +91,14 @@ public:
const QStringList &options() const
{ return m_options; }
const QStringList &includePaths() const
{ return m_includePaths; }
const QStringList &frameworkPaths() const
{ return m_frameworkPaths; }
const QList<CppTools::ProjectPart::HeaderPath> &headerPaths() const
{ return m_headerPaths; }
private:
ClangCodeModel::ClangCompleter::Ptr m_clangWrapper;
ClangCodeModel::Internal::UnsavedFiles m_unsavedFiles;
QStringList m_options, m_includePaths, m_frameworkPaths;
QStringList m_options;
QList<CppTools::ProjectPart::HeaderPath> m_headerPaths;
Internal::PchInfo::Ptr m_savedPchPointer;
};

View File

@@ -209,11 +209,25 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind
result << buildDefines(pPart->toolchainDefines, false);
result << buildDefines(pPart->projectDefines, false);
foreach (const QString &frameworkPath, pPart->frameworkPaths)
result.append(QLatin1String("-F") + frameworkPath);
foreach (const QString &inc, pPart->includePaths)
if (!inc.isEmpty() && !isBlacklisted(inc))
result << (QLatin1String("-I") + inc);
typedef ProjectPart::HeaderPath HeaderPath;
foreach (const HeaderPath &headerPath , pPart->headerPaths) {
if (headerPath.path.isEmpty() || isBlacklisted(headerPath.path))
continue;
QString prefix;
switch (headerPath.type) {
case HeaderPath::FrameworkPath:
prefix = QLatin1String("-F");
break;
default: // This shouldn't happen, but let's be nice..:
// intentional fall-through:
case HeaderPath::IncludePath:
prefix = QLatin1String("-I");
break;
}
result.append(prefix + headerPath.path);
}
#if 0
qDebug() << "--- m_args:";

View File

@@ -249,7 +249,8 @@ void PchManager::doPchInfoUpdateNone(QFutureInterface<void> &future,
void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
const PchManager::UpdateParams params)
{
QHash<QString, QSet<QString> > includes, frameworks;
typedef ProjectPart::HeaderPath HeaderPath;
QHash<QString, QSet<HeaderPath>> headers;
QHash<QString, QSet<QByteArray> > definesPerPCH;
QHash<QString, bool> objc;
QHash<QString, bool> cplusplus;
@@ -266,8 +267,7 @@ void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
continue;
inputToParts[pch].append(projectPart);
includes[pch].unite(QSet<QString>::fromList(projectPart->includePaths));
frameworks[pch].unite(QSet<QString>::fromList(projectPart->frameworkPaths));
headers[pch].unite(QSet<HeaderPath>::fromList(projectPart->headerPaths));
cVersions[pch] = std::max(cVersions.value(pch, ProjectPart::C89), projectPart->cVersion);
cxxVersions[pch] = std::max(cxxVersions.value(pch, ProjectPart::CXX98), projectPart->cxxVersion);
cxxExtensionsMap[pch] = cxxExtensionsMap[pch] | projectPart->cxxExtensions;
@@ -306,8 +306,7 @@ void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
projectPart->cVersion = cVersions[pch];
projectPart->cxxVersion = cxxVersions[pch];
projectPart->cxxExtensions = cxxExtensionsMap[pch];
projectPart->includePaths = includes[pch].toList();
projectPart->frameworkPaths = frameworks[pch].toList();
projectPart->headerPaths = headers[pch].toList();
QList<QByteArray> defines = definesPerPCH[pch].toList();
if (!defines.isEmpty()) {
@@ -378,22 +377,20 @@ void PchManager::doPchInfoUpdateCustom(QFutureInterface<void> &future,
future.setProgressRange(0, 1);
future.setProgressValue(0);
QSet<QString> includes, frameworks;
ProjectPart::HeaderPaths headers;
bool objc = false;
bool cplusplus = false;
ProjectPart::Ptr united(new ProjectPart());
united->cxxVersion = ProjectPart::CXX98;
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
includes.unite(QSet<QString>::fromList(projectPart->includePaths));
frameworks.unite(QSet<QString>::fromList(projectPart->frameworkPaths));
headers += projectPart->headerPaths;
united->cVersion = std::max(united->cVersion, projectPart->cVersion);
united->cxxVersion = std::max(united->cxxVersion, projectPart->cxxVersion);
united->qtVersion = std::max(united->qtVersion, projectPart->qtVersion);
objc |= hasObjCFiles(projectPart);
cplusplus |= hasCppFiles(projectPart);
}
united->frameworkPaths = frameworks.toList();
united->includePaths = includes.toList();
united->headerPaths = headers;
QStringList opts = Utils::createClangOptions(
united, getPrefixFileKind(objc, cplusplus));
united.clear();

View File

@@ -338,27 +338,32 @@ bool CMakeProject::parseCMakeLists()
CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
pinfo.clearProjectParts();
CppTools::ProjectPart::Ptr part(new CppTools::ProjectPart);
typedef CppTools::ProjectPart ProjectPart;
ProjectPart::Ptr part(new ProjectPart);
part->project = this;
part->displayName = displayName();
part->projectFile = projectFilePath().toString();
// This explicitly adds -I. to the include paths
part->includePaths += projectDirectory().toString();
part->headerPaths += ProjectPart::HeaderPath(projectDirectory().toString(),
ProjectPart::HeaderPath::IncludePath);
foreach (const QString &includeFile, cbpparser.includeFiles()) {
ProjectPart::HeaderPath hp(includeFile, ProjectPart::HeaderPath::IncludePath);
// CodeBlocks is utterly ignorant of frameworks on Mac, and won't report framework
// paths. The work-around is to check if the include path ends in ".framework", and
// if so, add the parent directory as framework path.
if (includeFile.endsWith(QLatin1String(".framework"))) {
const int slashIdx = includeFile.lastIndexOf(QLatin1Char('/'));
if (slashIdx != -1) {
part->frameworkPaths += includeFile.left(slashIdx);
hp = ProjectPart::HeaderPath(includeFile.left(slashIdx),
ProjectPart::HeaderPath::FrameworkPath);
continue;
}
}
part->includePaths += includeFile;
part->headerPaths += hp;
}
part->projectDefines += cbpparser.defines();

View File

@@ -1,4 +1,4 @@
<plugin name=\"Core\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_COMPAT_VERSION\">
<plugin name=\"Core\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_COMPAT_VERSION\" required=\"true\">
<vendor>Digia Plc</vendor>
<copyright>(C) 2014 Digia Plc</copyright>
<license>

View File

@@ -11,6 +11,12 @@ QtcPlugin {
"widgets", "xml", "network", "script", "sql", "help", "printsupport"
]
}
Depends {
name: "Qt.gui-private"
condition: qbs.targetOS.contains("windows") && Qt.core.versionMajor >= 5
}
Depends { name: "Utils" }
Depends { name: "Aggregation" }

View File

@@ -37,6 +37,7 @@
#include <coreplugin/dialogs/readonlyfilesdialog.h>
#include <coreplugin/dialogs/saveitemsdialog.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/editorview.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/ieditorfactory.h>
#include <coreplugin/editormanager/iexternaleditor.h>
@@ -1414,19 +1415,42 @@ void DocumentManager::executeOpenWithMenuAction(QAction *action)
const QVariant data = action->data();
OpenWithEntry entry = qvariant_cast<OpenWithEntry>(data);
if (entry.editorFactory) {
// close any open editors that have this file open, but have a different type.
// close any open editors that have this file open
// remember the views to open new editors in there
QList<Internal::EditorView *> views;
QList<IEditor *> editorsOpenForFile
= DocumentModel::editorsForFilePath(entry.fileName);
if (!editorsOpenForFile.isEmpty()) {
foreach (IEditor *openEditor, editorsOpenForFile) {
if (entry.editorFactory->id() == openEditor->document()->id())
editorsOpenForFile.removeAll(openEditor);
}
if (!EditorManager::closeEditors(editorsOpenForFile)) // don't open if cancel was pressed
return;
foreach (IEditor *openEditor, editorsOpenForFile) {
Internal::EditorView *view = EditorManager::viewForEditor(openEditor);
if (view && view->currentEditor() == openEditor) // visible
views.append(view);
}
if (!EditorManager::closeEditors(editorsOpenForFile)) // don't open if cancel was pressed
return;
EditorManager::openEditor(entry.fileName, entry.editorFactory->id());
if (views.isEmpty()) {
EditorManager::openEditor(entry.fileName, entry.editorFactory->id());
} else {
if (Internal::EditorView *currentView = EditorManager::currentEditorView()) {
if (views.removeOne(currentView))
views.prepend(currentView); // open editor in current view first
}
EditorManager::OpenEditorFlags flags;
foreach (Internal::EditorView *view, views) {
IEditor *editor =
EditorManager::openEditor(view, entry.fileName, entry.editorFactory->id(),
flags);
// Do not change the current editor after opening the first one. That
// * prevents multiple updates of focus etc which are not necessary
// * lets us control which editor is made current by putting the current editor view
// to the front (if that was in the list in the first place
flags |= EditorManager::DoNotChangeCurrentEditor;
// do not try to open more editors if this one failed, or editor type does not
// support duplication anyhow
if (!editor || !editor->duplicateSupported())
break;
}
}
return;
}
if (entry.externalEditor)

View File

@@ -213,7 +213,7 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
int index;
QString displayName = entry->displayName();
for (index = 0; index < m_entries.count(); ++index) {
if (displayName < m_entries.at(index)->displayName())
if (displayName.localeAwareCompare(m_entries.at(index)->displayName()) < 0)
break;
}
int row = index + 1/*<no document>*/;

View File

@@ -820,7 +820,7 @@ void EditorManager::addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentMod
contextMenu->addAction(d->m_closeAllEditorsExceptVisibleContextAction);
}
void EditorManager::addNativeDirActions(QMenu *contextMenu, DocumentModel::Entry *entry)
void EditorManager::addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry)
{
QTC_ASSERT(contextMenu, return);
bool enabled = entry && !entry->fileName().isEmpty();
@@ -830,6 +830,12 @@ void EditorManager::addNativeDirActions(QMenu *contextMenu, DocumentModel::Entry
contextMenu->addAction(d->m_openGraphicalShellAction);
contextMenu->addAction(d->m_openTerminalAction);
contextMenu->addAction(d->m_findInDirectoryAction);
QMenu *openWith = contextMenu->addMenu(tr("Open with"));
connect(openWith, SIGNAL(triggered(QAction*)),
DocumentManager::instance(), SLOT(executeOpenWithMenuAction(QAction*)));
openWith->setEnabled(enabled);
if (enabled)
DocumentManager::populateOpenWithMenu(openWith, entry->fileName());
}
static void setFocusToEditorViewAndUnmaximizePanes(EditorView *view)

View File

@@ -117,6 +117,8 @@ public:
static IEditor *openEditorWithContents(Id editorId, QString *titlePattern = 0,
const QByteArray &contents = QByteArray(),
OpenEditorFlags flags = NoFlags);
static IEditor *openEditor(Internal::EditorView *view, const QString &fileName,
Id id = Id(), OpenEditorFlags flags = NoFlags, bool *newEditor = 0);
static bool openExternalEditor(const QString &fileName, Id editorId);
@@ -125,6 +127,7 @@ public:
static IDocument *currentDocument();
static IEditor *currentEditor();
static Internal::EditorView *currentEditorView();
static QList<IEditor *> visibleEditors();
static void activateEditor(IEditor *editor, OpenEditorFlags flags = 0);
@@ -136,6 +139,8 @@ public:
static void closeEditor(DocumentModel::Entry *entry);
static void closeOtherEditors(IDocument *document);
static Internal::EditorView *viewForEditor(IEditor *editor);
static void addCurrentPositionToNavigationHistory(IEditor *editor = 0, const QByteArray &saveState = QByteArray());
static void cutForwardNavigationHistory();
@@ -186,7 +191,7 @@ public:
static QString windowTitleVcsTopic();
static void addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry);
static void addNativeDirActions(QMenu *contextMenu, DocumentModel::Entry *entry);
static void addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry);
signals:
void currentEditorChanged(Core::IEditor *editor);
@@ -264,14 +269,10 @@ private:
static void activateEditorForEntry(Internal::EditorView *view, DocumentModel::Entry *entry,
OpenEditorFlags flags = NoFlags);
static void activateView(Internal::EditorView *view);
static IEditor *openEditor(Internal::EditorView *view, const QString &fileName,
Id id = Id(), OpenEditorFlags flags = NoFlags, bool *newEditor = 0);
static int visibleDocumentsCount();
static void setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory = false);
static void setCurrentView(Internal::EditorView *view);
static Internal::EditorView *currentEditorView();
static Internal::EditorView *viewForEditor(IEditor *editor);
static Internal::SplitterOrView *findRoot(const Internal::EditorView *view, int *rootIndex = 0);
static void closeView(Internal::EditorView *view);

View File

@@ -208,7 +208,7 @@ void OpenEditorsWidget::contextMenuRequested(QPoint pos)
m_model->mapToSource(editorIndex).row());
EditorManager::addSaveAndCloseEditorActions(&contextMenu, entry);
contextMenu.addSeparator();
EditorManager::addNativeDirActions(&contextMenu, entry);
EditorManager::addNativeDirAndOpenWithActions(&contextMenu, entry);
contextMenu.exec(mapToGlobal(pos));
}

View File

@@ -325,7 +325,7 @@ void EditorToolBar::listContextMenu(QPoint pos)
menu.addSeparator();
EditorManager::addSaveAndCloseEditorActions(&menu, entry);
menu.addSeparator();
EditorManager::addNativeDirActions(&menu, entry);
EditorManager::addNativeDirAndOpenWithActions(&menu, entry);
QAction *result = menu.exec(d->m_editorList->mapToGlobal(pos));
if (result == copyPath)
QApplication::clipboard()->setText(QDir::toNativeSeparators(fileName));

View File

@@ -57,7 +57,7 @@ public:
};
Q_DECLARE_FLAGS(WizardFlags, WizardFlag)
IWizardFactory() { }
IWizardFactory() : m_kind(FileWizard) { }
QString id() const { return m_id; }
WizardKind kind() const { return m_kind; }

View File

@@ -89,7 +89,9 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<Core::Lo
dirFilter |= QDir::Hidden;
fileFilter |= QDir::Hidden;
}
const Qt::CaseSensitivity caseSensitivity_ = caseSensitivity(entry);
// use only 'name' for case sensitivity decision, because we need to make the path
// match the case on the file system for case-sensitive file systems
const Qt::CaseSensitivity caseSensitivity_ = caseSensitivity(name);
QStringList dirs = dirInfo.entryList(dirFilter,
QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
QStringList files = dirInfo.entryList(fileFilter,

View File

@@ -339,6 +339,13 @@ IVersionControl* VcsManager::findVersionControlForDirectory(const QString &input
return versionControl;
}
QString VcsManager::findTopLevelForDirectory(const QString &directory)
{
QString result;
findVersionControlForDirectory(directory, &result);
return result;
}
QStringList VcsManager::repositories(const IVersionControl *vc)
{
QStringList result;

View File

@@ -65,6 +65,7 @@ public:
static void resetVersionControlForDirectory(const QString &inputDirectory);
static IVersionControl *findVersionControlForDirectory(const QString &directory,
QString *topLevelDirectory = 0);
static QString findTopLevelForDirectory(const QString &directory);
static QStringList repositories(const IVersionControl *);

View File

@@ -1446,7 +1446,7 @@ void CppCodeModelInspectorDialog::refresh()
}
// Merged entities
dumper.dumpMergedEntities(cmmi->includePaths(), cmmi->frameworkPaths(), cmmi->definedMacros());
dumper.dumpMergedEntities(cmmi->headerPaths(), cmmi->definedMacros());
}
enum DocumentTabs {
@@ -1559,8 +1559,7 @@ enum ProjectPartTabs {
ProjectPartGeneralTab,
ProjectPartFilesTab,
ProjectPartDefinesTab,
ProjectPartIncludePathsTab,
ProjectPartFrameworkPathsTab,
ProjectPartHeaderPathsTab,
ProjectPartPrecompiledHeadersTab
};
@@ -1570,8 +1569,7 @@ static QString partTabName(int tabIndex, int numberOfEntries = -1)
"&General",
"Project &Files",
"&Defines",
"&Include Paths",
"F&ramework Paths",
"&Header Paths",
"Pre&compiled Headers"
};
QString result = QLatin1String(names[tabIndex]);
@@ -1591,13 +1589,9 @@ void CppCodeModelInspectorDialog::clearProjectPartData()
m_ui->partProjectDefinesEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab, partTabName(ProjectPartDefinesTab));
m_ui->partIncludePathsEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartIncludePathsTab,
partTabName(ProjectPartIncludePathsTab));
m_ui->partFrameworkPathsEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartFrameworkPathsTab,
partTabName(ProjectPartFrameworkPathsTab));
m_ui->partHeaderPathsEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
partTabName(ProjectPartHeaderPathsTab));
m_ui->partPrecompiledHeadersEdit->setPlainText(QString());
m_ui->projectPartTab->setTabText(ProjectPartPrecompiledHeadersTab,
@@ -1654,15 +1648,10 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab,
partTabName(ProjectPartDefinesTab, numberOfDefines));
// Include Paths
m_ui->partIncludePathsEdit->setPlainText(CMI::Utils::pathListToString(part->includePaths));
m_ui->projectPartTab->setTabText(ProjectPartIncludePathsTab,
partTabName(ProjectPartIncludePathsTab, part->includePaths.size()));
// Framework Paths
m_ui->partFrameworkPathsEdit->setPlainText(CMI::Utils::pathListToString(part->frameworkPaths));
m_ui->projectPartTab->setTabText(ProjectPartFrameworkPathsTab,
partTabName(ProjectPartFrameworkPathsTab, part->frameworkPaths.size()));
// Header Paths
m_ui->partHeaderPathsEdit->setPlainText(CMI::Utils::pathListToString(part->headerPaths));
m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
partTabName(ProjectPartHeaderPathsTab, part->headerPaths.size()));
// Precompiled Headers
m_ui->partPrecompiledHeadersEdit->setPlainText(

View File

@@ -261,25 +261,11 @@
</widget>
<widget class="QWidget" name="tab_15">
<attribute name="title">
<string notr="true">&amp;Include Paths</string>
<string notr="true">&amp;Header Paths</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_16">
<item>
<widget class="QPlainTextEdit" name="partIncludePathsEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="definesTab_2">
<attribute name="title">
<string notr="true">F&amp;ramework Paths</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
<widget class="QPlainTextEdit" name="partFrameworkPathsEdit">
<widget class="QPlainTextEdit" name="partHeaderPathsEdit">
<property name="readOnly">
<bool>true</bool>
</property>

View File

@@ -182,6 +182,7 @@ private slots:
void test_quickfix_MoveFuncDefOutside_afterClass();
void test_quickfix_MoveFuncDefOutside_respectWsInOperatorNames1();
void test_quickfix_MoveFuncDefOutside_respectWsInOperatorNames2();
void test_quickfix_MoveFuncDefOutside_macroUses();
void test_quickfix_MoveFuncDefToDecl_MemberFunc();
void test_quickfix_MoveFuncDefToDecl_MemberFuncOutside();
@@ -192,6 +193,7 @@ private slots:
void test_quickfix_MoveFuncDefToDecl_FreeFuncToCppNS();
void test_quickfix_MoveFuncDefToDecl_CtorWithInitialization();
void test_quickfix_MoveFuncDefToDecl_structWithAssignedVariable();
void test_quickfix_MoveFuncDefToDecl_macroUses();
void test_quickfix_AssignToLocalVariable_templates();

View File

@@ -310,9 +310,10 @@ CPPEditorWidget::Link attemptFuncDeclDef(const QTextCursor &cursor,
CPPEditorWidget *, CPlusPlus::Snapshot snapshot, const CPlusPlus::Document::Ptr &document,
SymbolFinder *symbolFinder)
{
snapshot.insert(document);
Link result;
QTC_ASSERT(document, return result);
snapshot.insert(document);
QList<AST *> path = ASTPath(document)(cursor);
@@ -518,7 +519,7 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &
}
// Check if we're on an operator declaration or definition.
if (!recognizedQtMethod) {
if (!recognizedQtMethod && documentFromSemanticInfo) {
bool cursorRegionReached = false;
for (int i = 0; i < tokens.size(); ++i) {
const Token &tk = tokens.at(i);

View File

@@ -123,11 +123,12 @@ static QString &removeTrailingWhitespace(QString &input)
/// Exactly one TestFile must contain the cursor position marker '@' in the originalSource.
QuickFixTestCase::QuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &theTestFiles,
CppQuickFixFactory *factory,
const QStringList &includePaths,
int resultIndex)
const ProjectPart::HeaderPaths &headerPaths,
int resultIndex,
const QByteArray &expectedFailMessage)
: m_testFiles(theTestFiles)
, m_cppCodeStylePreferences(0)
, m_restoreIncludePaths(false)
, m_restoreHeaderPaths(false)
{
QVERIFY(succeededSoFar());
@@ -144,10 +145,10 @@ QuickFixTestCase::QuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &theTe
testFile->writeToDisk();
// Set appropriate include paths
if (!includePaths.isEmpty()) {
m_restoreIncludePaths = true;
m_includePathsToRestore = m_modelManager->includePaths();
m_modelManager->setIncludePaths(includePaths);
if (!headerPaths.isEmpty()) {
m_restoreHeaderPaths = true;
m_headerPathsToRestore = m_modelManager->headerPaths();
m_modelManager->setHeaderPaths(headerPaths);
}
// Update Code Model
@@ -196,6 +197,8 @@ QuickFixTestCase::QuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &theTe
// Check
QString result = testFile->m_editorWidget->document()->toPlainText();
removeTrailingWhitespace(result);
if (!expectedFailMessage.isEmpty())
QEXPECT_FAIL("", expectedFailMessage.data(), Continue);
QCOMPARE(result, testFile->m_expectedSource);
// Undo the change
@@ -213,14 +216,22 @@ QuickFixTestCase::~QuickFixTestCase()
m_cppCodeStylePreferences->setCurrentDelegate(m_cppCodeStylePreferencesOriginalDelegateId);
// Restore include paths
if (m_restoreIncludePaths)
m_modelManager->setIncludePaths(m_includePathsToRestore);
if (m_restoreHeaderPaths)
m_modelManager->setHeaderPaths(m_headerPathsToRestore);
// Remove created files from file system
foreach (const QuickFixTestDocument::Ptr &testDocument, m_testFiles)
QVERIFY(QFile::remove(testDocument->filePath()));
}
void QuickFixTestCase::run(const QList<QuickFixTestDocument::Ptr> &theTestFiles,
CppQuickFixFactory *factory, const QString &incPath)
{
ProjectPart::HeaderPaths hps;
hps += ProjectPart::HeaderPath(incPath, ProjectPart::HeaderPath::IncludePath);
QuickFixTestCase(theTestFiles, factory, hps);
}
/// Delegates directly to AddIncludeForUndefinedIdentifierOp for easier testing.
class AddIncludeForUndefinedIdentifierTestFactory : public CppQuickFixFactory
{
@@ -1289,7 +1300,7 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_afterClass()
testFiles << QuickFixTestDocument::create("file.cpp", original, expected);
InsertDefFromDecl factory;
QuickFixTestCase(testFiles, &factory, QStringList(), 1);
QuickFixTestCase(testFiles, &factory, ProjectPart::HeaderPaths(), 1);
}
/// Check from header file: If there is a source file, insert the definition in the source file.
@@ -1478,7 +1489,7 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_insideClass()
"};";
InsertDefFromDecl factory;
QuickFixTestCase(singleDocument(original, expected), &factory, QStringList(), 1);
QuickFixTestCase(singleDocument(original, expected), &factory, ProjectPart::HeaderPaths(), 1);
}
/// Check not triggering when definition exists
@@ -1492,7 +1503,8 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_notTriggeringWhenDefinitio
const QByteArray expected = original;
InsertDefFromDecl factory;
QuickFixTestCase test(singleDocument(original, expected), &factory, QStringList(), 1);
QuickFixTestCase test(singleDocument(original, expected), &factory, ProjectPart::HeaderPaths(),
1);
}
/// Find right implementation file.
@@ -1910,7 +1922,7 @@ void insertToSectionDeclFromDef(const QByteArray &section, int sectionIndex)
testFiles << QuickFixTestDocument::create("file.cpp", original, expected);
InsertDeclFromDef factory;
QuickFixTestCase(testFiles, &factory, QStringList(), sectionIndex);
QuickFixTestCase(testFiles, &factory, ProjectPart::HeaderPaths(), sectionIndex);
}
/// Check from source file: Insert in header file.
@@ -1961,7 +1973,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_normal()
// Do not use the test factory, at least once we want to go through the "full stack".
AddIncludeForUndefinedIdentifier factory;
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Ignore *.moc includes
@@ -1986,7 +1998,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_ignoremoc()
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert include at top for a sorted group
@@ -2012,7 +2024,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_sortingTop(
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert include in the middle for a sorted group
@@ -2038,7 +2050,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_sortingMidd
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert include at bottom for a sorted group
@@ -2064,7 +2076,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_sortingBott
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: For an unsorted group the new include is appended
@@ -2090,7 +2102,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_appendToUns
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert a local include at front if there are only global includes
@@ -2117,7 +2129,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_firstLocalI
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert a global include at back if there are only local includes
@@ -2146,7 +2158,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_firstGlobal
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("<file.h>"));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Prefer group with longest matching prefix
@@ -2176,7 +2188,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_preferGroup
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"prefixc.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Create a new include group if there are only include groups with a different include dir
@@ -2203,7 +2215,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_newGroupIfO
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Include group with mixed include dirs, sorted --> insert properly
@@ -2231,7 +2243,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_mixedDirsSo
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("<firstlib/file.h>"));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Include group with mixed include dirs, unsorted --> append
@@ -2259,7 +2271,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_mixedDirsUn
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("<lastlib/file.h>"));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Include group with mixed include types
@@ -2285,7 +2297,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_mixedInclud
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"z.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Include group with mixed include types
@@ -2311,7 +2323,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_mixedInclud
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"a.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Include group with mixed include types
@@ -2337,7 +2349,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_mixedInclud
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"lib/file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Include group with mixed include types
@@ -2363,7 +2375,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_mixedInclud
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("<lib/file.h>"));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert very first include
@@ -2386,7 +2398,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_noinclude()
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert very first include if there is a c++ style comment on top
@@ -2415,7 +2427,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_veryFirstIn
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: Insert very first include if there is a c style comment on top
@@ -2448,7 +2460,7 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_veryFirstIn
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifierTestFactory factory(QLatin1String("\"file.h\""));
QuickFixTestCase(testFiles, &factory, QStringList(TestIncludePaths::globalIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalIncludePath());
}
/// Check: If a "Qt Class" was not found by the locator, check the header files in the Qt
@@ -2472,8 +2484,8 @@ void CppEditorPlugin::test_quickfix_AddIncludeForUndefinedIdentifier_checkQSomet
+ "/file.cpp", original, expected);
AddIncludeForUndefinedIdentifier factory;
QuickFixTestCase(testFiles,&factory,
QStringList(CppTools::Tests::TestIncludePaths::globalQtCoreIncludePath()));
QuickFixTestCase::run(testFiles, &factory, TestIncludePaths::globalQtCoreIncludePath());
}
/// Check: Move definition from header to cpp.
@@ -2638,7 +2650,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside2()
testFiles << QuickFixTestDocument::create("file.cpp", original, expected);
MoveFuncDefOutside factory;
QuickFixTestCase(testFiles, &factory, QStringList(), 1);
QuickFixTestCase(testFiles, &factory, ProjectPart::HeaderPaths(), 1);
}
/// Check: Move definition from header to cpp (with namespace).
@@ -2951,7 +2963,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_afterClass()
testFiles << QuickFixTestDocument::create("file.cpp", original, expected);
MoveFuncDefOutside factory;
QuickFixTestCase(testFiles, &factory, QStringList(), 1);
QuickFixTestCase(testFiles, &factory, ProjectPart::HeaderPaths(), 1);
}
/// Check if whitespace is respected for operator functions
@@ -2998,6 +3010,39 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_respectWsInOperatorNames2
QuickFixTestCase(singleDocument(original, expected), &factory);
}
void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_macroUses()
{
QByteArray original =
"#define CONST const\n"
"#define VOLATILE volatile\n"
"class Foo\n"
"{\n"
" int fu@nc(int a, int b) CONST VOLATILE\n"
" {\n"
" return 42;\n"
" }\n"
"};\n";
QByteArray expected =
"#define CONST const\n"
"#define VOLATILE volatile\n"
"class Foo\n"
"{\n"
" int func(int a, int b) CONST VOLATILE;\n"
"};\n"
"\n"
"\n"
// const volatile become lowercase: QTCREATORBUG-12620
"int Foo::func(int a, int b) const volatile\n"
"{\n"
" return 42;\n"
"}\n"
;
MoveFuncDefOutside factory;
QuickFixTestCase(singleDocument(original, expected), &factory,
ProjectPart::HeaderPaths(), 0, "QTCREATORBUG-12314");
}
/// Check: revert test_quickfix_MoveFuncDefOutside_MemberFuncToCpp()
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_MemberFunc()
{
@@ -3301,6 +3346,37 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_structWithAssignedVariable
QuickFixTestCase(singleDocument(original, expected), &factory);
}
void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_macroUses()
{
QByteArray original =
"#define CONST const\n"
"#define VOLATILE volatile\n"
"class Foo\n"
"{\n"
" int func(int a, int b) CONST VOLATILE;\n"
"};\n"
"\n"
"\n"
"int Foo::fu@nc(int a, int b) CONST VOLATILE"
"{\n"
" return 42;\n"
"}\n";
QByteArray expected =
"#define CONST const\n"
"#define VOLATILE volatile\n"
"class Foo\n"
"{\n"
" int func(int a, int b) CONST VOLATILE\n"
" {\n"
" return 42;\n"
" }\n"
"};\n\n\n\n";
MoveFuncDefToDecl factory;
QuickFixTestCase(singleDocument(original, expected), &factory,
ProjectPart::HeaderPaths(), 0, "QTCREATORBUG-12314");
}
void CppEditorPlugin::test_quickfix_AssignToLocalVariable_templates()
{

View File

@@ -74,10 +74,14 @@ class QuickFixTestCase : public TestCase
public:
QuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &theTestFiles,
CppQuickFixFactory *factory,
const QStringList &includePaths = QStringList(),
int resultIndex = 0);
const CppTools::ProjectPart::HeaderPaths &includePaths =
CppTools::ProjectPart::HeaderPaths(),
int resultIndex = 0,
const QByteArray &expectedFailMessage = QByteArray());
~QuickFixTestCase();
static void run(const QList<QuickFixTestDocument::Ptr> &theTestFiles,
CppQuickFixFactory *factory, const QString &incPath);
private:
QSharedPointer<TextEditor::QuickFixOperation> getFix(CppQuickFixFactory *factory,
CPPEditorWidget *editorWidget,
@@ -89,8 +93,8 @@ private:
CppTools::CppCodeStylePreferences *m_cppCodeStylePreferences;
QByteArray m_cppCodeStylePreferencesOriginalDelegateId;
QStringList m_includePathsToRestore;
bool m_restoreIncludePaths;
CppTools::ProjectPart::HeaderPaths m_headerPathsToRestore;
bool m_restoreHeaderPaths;
};
QList<QuickFixTestDocument::Ptr> singleDocument(const QByteArray &original,

View File

@@ -1896,7 +1896,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
return;
// find the include paths
QStringList includePaths;
ProjectPart::HeaderPaths headerPaths;
CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
QList<CppModelManagerInterface::ProjectInfo> projectInfos = modelManager->projectInfos();
bool inProject = false;
@@ -1905,14 +1905,14 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
foreach (const ProjectFile &file, part->files) {
if (file.path == doc->fileName()) {
inProject = true;
includePaths += part->includePaths;
headerPaths += part->headerPaths;
}
}
}
}
if (!inProject) {
// better use all include paths than none
includePaths = modelManager->includePaths();
headerPaths = modelManager->headerPaths();
}
// find a include file through the locator
@@ -1933,10 +1933,10 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
if (fileInfo.path() == QFileInfo(doc->fileName()).path()) {
shortestInclude = QLatin1Char('"') + fileInfo.fileName() + QLatin1Char('"');
} else {
foreach (const QString &includePath, includePaths) {
if (!fileName.startsWith(includePath))
foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) {
if (!fileName.startsWith(headerPath.path))
continue;
QString relativePath = fileName.mid(includePath.size());
QString relativePath = fileName.mid(headerPath.path.size());
if (!relativePath.isEmpty() && relativePath.at(0) == QLatin1Char('/'))
relativePath = relativePath.mid(1);
if (shortestInclude.isEmpty() || relativePath.size() + 2 < shortestInclude.size())
@@ -1965,11 +1965,11 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
// otherwise, check for a header file with the same name in the Qt include paths
} else {
foreach (const QString &includePath, includePaths) {
if (!includePath.contains(QLatin1String("/Qt"))) // "QtCore", "QtGui" etc...
foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) {
if (!headerPath.path.contains(QLatin1String("/Qt"))) // "QtCore", "QtGui" etc...
continue;
const QString headerPathCandidate = includePath + QLatin1Char('/') + className;
const QString headerPathCandidate = headerPath.path + QLatin1Char('/') + className;
const QFileInfo fileInfo(headerPathCandidate);
if (fileInfo.exists() && fileInfo.isFile()) {
const QString include = QLatin1Char('<') + className + QLatin1Char('>');

View File

@@ -51,7 +51,7 @@ static void parse(QFutureInterface<void> &future,
bool processingHeaders = false;
CppModelManager *cmm = CppModelManager::instance();
const QStringList fallbackIncludePaths = cmm->includePaths();
const ProjectPart::HeaderPaths fallbackHeaderPaths = cmm->headerPaths();
for (int i = 0; i < files.size(); ++i) {
if (future.isPaused())
future.waitForResume();
@@ -71,10 +71,10 @@ static void parse(QFutureInterface<void> &future,
}
QList<ProjectPart::Ptr> parts = cmm->projectPart(fileName);
QStringList includePaths = parts.isEmpty()
? fallbackIncludePaths
: parts.first()->includePaths;
sourceProcessor->setIncludePaths(includePaths);
ProjectPart::HeaderPaths headerPaths = parts.isEmpty()
? fallbackHeaderPaths
: parts.first()->headerPaths;
sourceProcessor->setHeaderPaths(headerPaths);
sourceProcessor->run(fileName);
future.setProgressValue(files.size() - sourceProcessor->todo().size());
@@ -190,8 +190,7 @@ QFuture<void> BuiltinIndexingSupport::refreshSourceFiles(const QStringList &sour
CppSourceProcessor *preproc = CppModelManager::createSourceProcessor();
preproc->setDumpFileNameWhileParsing(m_dumpFileNameWhileParsing);
preproc->setRevision(++m_revision);
preproc->setIncludePaths(mgr->includePaths());
preproc->setFrameworkPaths(mgr->frameworkPaths());
preproc->setHeaderPaths(mgr->headerPaths());
preproc->setWorkingCopy(workingCopy);
QFuture<void> result = QtConcurrent::run(&parse, preproc, sourceFiles);

View File

@@ -413,6 +413,18 @@ QString Utils::pathListToString(const QStringList &pathList)
return result.join(QLatin1String("\n"));
}
QString Utils::pathListToString(const ProjectPart::HeaderPaths &pathList)
{
QStringList result;
foreach (const ProjectPart::HeaderPath &path, pathList) {
result << QString(QLatin1String("%1 (%2 path)")).arg(
QDir::toNativeSeparators(path.path),
path.isFrameworkPath() ? QLatin1String("framework") : QLatin1String("include")
);
}
return result.join(QLatin1String("\n"));
}
QList<CPlusPlus::Document::Ptr> Utils::snapshotToList(const CPlusPlus::Snapshot &snapshot)
{
QList<CPlusPlus::Document::Ptr> documents;
@@ -511,16 +523,14 @@ void Dumper::dumpProjectInfos( const QList<CppModelManagerInterface::ProjectInfo
m_out << i4 << defineLine << "\n";
}
if (!part->includePaths.isEmpty()) {
m_out << i3 << "Include Paths:{{{4\n";
foreach (const QString &includePath, part->includePaths)
m_out << i4 << includePath << "\n";
}
if (!part->frameworkPaths.isEmpty()) {
m_out << i3 << "Framework Paths:{{{4\n";
foreach (const QString &frameworkPath, part->frameworkPaths)
m_out << i4 << frameworkPath << "\n";
if (!part->headerPaths.isEmpty()) {
m_out << i3 << "Header Paths:{{{4\n";
foreach (const ProjectPart::HeaderPath &headerPath, part->headerPaths)
m_out << i4 << headerPath.path
<< (headerPath.type == ProjectPart::HeaderPath::IncludePath
? "(include path)"
: "(framework path)")
<< "\n";
}
if (!part->precompiledHeaders.isEmpty()) {
@@ -582,18 +592,18 @@ void Dumper::dumpWorkingCopy(const CppModelManagerInterface::WorkingCopy &workin
}
}
void Dumper::dumpMergedEntities(const QStringList &mergedIncludePaths,
const QStringList &mergedFrameworkPaths,
void Dumper::dumpMergedEntities(const ProjectPart::HeaderPaths &mergedHeaderPaths,
const QByteArray &mergedMacros)
{
m_out << "Merged Entities{{{1\n";
const QByteArray i2 = indent(2);
const QByteArray i3 = indent(3);
m_out << i2 << "Merged Include Paths{{{2\n";
dumpStringList(mergedIncludePaths, i3);
m_out << i2 << "Merged Framework Paths{{{2\n";
dumpStringList(mergedFrameworkPaths, i3);
m_out << i2 << "Merged Header Paths{{{2\n";
foreach (const ProjectPart::HeaderPath &hp, mergedHeaderPaths)
m_out << i3 << hp.path
<< (hp.isFrameworkPath() ? " (framework path)" : " (include path)")
<< "\n";
m_out << i2 << "Merged Defines{{{2\n";
m_out << mergedMacros;
}

View File

@@ -58,6 +58,7 @@ struct CPPTOOLS_EXPORT Utils
static QString partsForFile(const QString &fileName);
static QString unresolvedFileNameWithDelimiters(const CPlusPlus::Document::Include &include);
static QString pathListToString(const QStringList &pathList);
static QString pathListToString(const ProjectPart::HeaderPaths &pathList);
static QList<CPlusPlus::Document::Ptr> snapshotToList(const CPlusPlus::Snapshot &snapshot);
};
@@ -73,8 +74,7 @@ public:
const QString &title,
bool isGlobalSnapshot = false);
void dumpWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy);
void dumpMergedEntities(const QStringList &mergedIncludePaths,
const QStringList &mergedFrameworkPaths,
void dumpMergedEntities(const ProjectPart::HeaderPaths &mergedHeaderPaths,
const QByteArray &mergedMacros);
private:

View File

@@ -105,7 +105,7 @@ public:
= new CppCompletionAssistInterface(m_editorWidget->document(), m_position,
m_editorWidget->baseTextDocument()->filePath(),
ExplicitlyInvoked, m_snapshot,
QStringList(), QStringList());
ProjectPart::HeaderPaths());
CppCompletionAssistProcessor processor;
IAssistProposal *proposal = processor.perform(ai);
if (!proposal)
@@ -2263,6 +2263,24 @@ void CppToolsPlugin::test_completion_data()
) << _("n2.n1.t.") << (QStringList()
<< QLatin1String("foo")
<< QLatin1String("Foo"));
QTest::newRow("lambda_parameter") << _(
"auto func = [](int arg1) { return @; };\n"
) << _("ar") << (QStringList()
<< QLatin1String("arg1"));
QTest::newRow("default_arguments_for_class_templates_and_base_class_QTCREATORBUG-12605") << _(
"struct Foo { int foo; };\n"
"template <typename T = Foo>\n"
"struct Derived : T {};\n"
"void fun() {\n"
" Derived<> derived;\n"
" @\n"
"}\n"
) << _("derived.") << (QStringList()
<< QLatin1String("Derived")
<< QLatin1String("foo")
<< QLatin1String("Foo"));
}
void CppToolsPlugin::test_completion_member_access_operator()

View File

@@ -1139,30 +1139,23 @@ bool CppCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
}
// Make completion for all relevant includes
QStringList includePaths = m_interface->includePaths();
const QString &currentFilePath = QFileInfo(m_interface->fileName()).path();
if (!includePaths.contains(currentFilePath))
includePaths.append(currentFilePath);
ProjectPart::HeaderPaths headerPaths = m_interface->headerPaths();
const ProjectPart::HeaderPath currentFilePath(QFileInfo(m_interface->fileName()).path(),
ProjectPart::HeaderPath::IncludePath);
if (!headerPaths.contains(currentFilePath))
headerPaths.append(currentFilePath);
const Core::MimeType mimeType =
Core::MimeDatabase::findByType(QLatin1String("text/x-c++hdr"));
const QStringList suffixes = mimeType.suffixes();
foreach (const QString &includePath, includePaths) {
QString realPath = includePath;
foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) {
QString realPath = headerPath.path;
if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/');
realPath += directoryPrefix;
}
completeInclude(realPath, suffixes);
}
foreach (const QString &frameworkPath, m_interface->frameworkPaths()) {
QString realPath = frameworkPath;
if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/');
realPath += directoryPrefix;
realPath += QLatin1String(".framework/Headers");
if (headerPath.isFrameworkPath())
realPath += QLatin1String(".framework/Headers");
}
completeInclude(realPath, suffixes);
}
@@ -1969,8 +1962,7 @@ void CppCompletionAssistInterface::getCppSpecifics() const
if (QSharedPointer<SnapshotUpdater> updater = supp->snapshotUpdater()) {
updater->update(m_workingCopy);
m_snapshot = updater->snapshot();
m_includePaths = updater->includePaths();
m_frameworkPaths = updater->frameworkPaths();
m_headerPaths = updater->headerPaths();
}
}
}

View File

@@ -191,22 +191,20 @@ public:
const QString &fileName,
TextEditor::AssistReason reason,
const CPlusPlus::Snapshot &snapshot,
const QStringList &includePaths,
const QStringList &frameworkPaths)
const ProjectPart::HeaderPaths &headerPaths)
: TextEditor::DefaultAssistInterface(textDocument, position, fileName, reason)
, m_editor(0)
, m_isObjCEnabled(false)
, m_gotCppSpecifics(true)
, m_snapshot(snapshot)
, m_includePaths(includePaths)
, m_frameworkPaths(frameworkPaths)
, m_headerPaths(headerPaths)
{}
bool isObjCEnabled() const { return m_isObjCEnabled; }
const CPlusPlus::Snapshot &snapshot() const { getCppSpecifics(); return m_snapshot; }
const QStringList &includePaths() const { getCppSpecifics(); return m_includePaths; }
const QStringList &frameworkPaths() const { getCppSpecifics(); return m_frameworkPaths; }
const ProjectPart::HeaderPaths &headerPaths() const
{ getCppSpecifics(); return m_headerPaths; }
private:
void getCppSpecifics() const;
@@ -216,8 +214,7 @@ private:
mutable bool m_gotCppSpecifics;
CppModelManagerInterface::WorkingCopy m_workingCopy;
mutable CPlusPlus::Snapshot m_snapshot;
mutable QStringList m_includePaths;
mutable QStringList m_frameworkPaths;
mutable ProjectPart::HeaderPaths m_headerPaths;
};
} // Internal

View File

@@ -39,12 +39,9 @@ namespace {
class FindLocalSymbols: protected ASTVisitor
{
Scope *_functionScope;
Document::Ptr _doc;
public:
FindLocalSymbols(Document::Ptr doc)
: ASTVisitor(doc->translationUnit()), _doc(doc)
: ASTVisitor(doc->translationUnit())
{ }
// local and external uses.
@@ -59,12 +56,10 @@ public:
if (FunctionDefinitionAST *def = ast->asFunctionDefinition()) {
if (def->symbol) {
_functionScope = def->symbol;
accept(ast);
}
} else if (ObjCMethodDeclarationAST *decl = ast->asObjCMethodDeclaration()) {
if (decl->method_prototype->symbol) {
_functionScope = decl->method_prototype->symbol;
accept(ast);
}
}
@@ -180,6 +175,19 @@ protected:
_scopeStack.removeLast();
}
virtual bool visit(LambdaExpressionAST *ast)
{
if (ast->lambda_declarator && ast->lambda_declarator->symbol)
enterScope(ast->lambda_declarator->symbol);
return true;
}
virtual void endVisit(LambdaExpressionAST *ast)
{
if (ast->lambda_declarator && ast->lambda_declarator->symbol)
_scopeStack.removeLast();
}
virtual bool visit(CompoundStatementAST *ast)
{
if (ast->symbol)

View File

@@ -0,0 +1,200 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** 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.
**
** GNU Lesser General Public License Usage
** 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
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "cpptoolsplugin.h"
#include "cpplocalsymbols.h"
#include "cppsemanticinfo.h"
#include <cplusplus/Overview.h>
#include <utils/algorithm.h>
#include <QtTest>
namespace {
class FindFirstFunctionDefinition: protected CPlusPlus::ASTVisitor
{
public:
FindFirstFunctionDefinition(CPlusPlus::TranslationUnit *translationUnit)
: ASTVisitor(translationUnit)
, m_definition(0)
{}
CPlusPlus::FunctionDefinitionAST *operator()()
{
accept(translationUnit()->ast());
return m_definition;
}
private:
bool preVisit(CPlusPlus::AST *ast)
{
if (CPlusPlus::FunctionDefinitionAST *f = ast->asFunctionDefinition()) {
m_definition = f;
return false;
}
return true;
}
private:
CPlusPlus::FunctionDefinitionAST *m_definition;
};
struct Result
{
Result() : line(0), column(0), length(0) {}
Result(const QByteArray &name, unsigned line, unsigned column, unsigned length)
: name(name), line(line), column(column), length(length)
{}
QByteArray name;
unsigned line;
unsigned column;
unsigned length;
bool operator==(const Result &other) const
{
return name == other.name
&& line == other.line
&& column == other.column
&& length == other.length;
}
static Result fromHighlightingResult(const CPlusPlus::Symbol *symbol,
TextEditor::HighlightingResult result)
{
const QByteArray name = CPlusPlus::Overview().prettyName(symbol->name()).toLatin1();
return Result(name, result.line, result.column, result.length);
}
static QList<Result> fromLocalUses(CppTools::SemanticInfo::LocalUseMap localUses)
{
QList<Result> result;
CppTools::SemanticInfo::LocalUseIterator it(localUses);
while (it.hasNext()) {
it.next();
const CPlusPlus::Symbol *symbol = it.key();
const QList<CppTools::SemanticInfo::Use> &uses = it.value();
foreach (const CppTools::SemanticInfo::Use &use, uses)
result << fromHighlightingResult(symbol, use);
}
Utils::sort(result, [](const Result &r1, const Result &r2) -> bool {
if (r1.line == r2.line)
return r1.column < r2.column;
return r1.line < r2.line;
});
return result;
}
};
} // anonymous namespace
Q_DECLARE_METATYPE(Result)
Q_DECLARE_METATYPE(QList<Result>)
QT_BEGIN_NAMESPACE
namespace QTest {
template<>
char *toString(const Result &result)
{
QByteArray ba = "Result(";
ba += "_(\"" + result.name + "\"), ";
ba += QByteArray::number(result.line) + ", ";
ba += QByteArray::number(result.column) + ", ";
ba += QByteArray::number(result.length) + ")";
return qstrdup(ba.data());
}
}
QT_END_NAMESPACE
namespace CppTools {
namespace Internal {
void CppToolsPlugin::test_cpplocalsymbols_data()
{
QTest::addColumn<QByteArray>("source");
QTest::addColumn<QList<Result>>("expectedUses");
typedef QByteArray _;
QTest::newRow("basic")
<< _("int f(int arg)\n"
"{\n"
" int local;\n"
" g(&local);\n"
" return local + arg;\n"
"}\n")
<< (QList<Result>()
<< Result(_("arg"), 0, 10, 3)
<< Result(_("local"), 2, 9, 5)
<< Result(_("local"), 3, 8, 5)
<< Result(_("local"), 4, 12, 5)
<< Result(_("arg"), 4, 20, 3));
QTest::newRow("lambda")
<< _("void f()\n"
"{\n"
" auto func = [](int arg) { return arg; };\n"
" func(1);\n"
"}\n")
<< (QList<Result>()
<< Result(_("func"), 2, 10, 4)
<< Result(_("arg"), 2, 24, 3)
<< Result(_("arg"), 2, 38, 3)
<< Result(_("func"), 3, 5, 4));
}
void CppToolsPlugin::test_cpplocalsymbols()
{
QFETCH(QByteArray, source);
QFETCH(QList<Result>, expectedUses);
CPlusPlus::Document::Ptr document = CPlusPlus::Document::create(QLatin1String("test.cpp"));
document->setUtf8Source(source);
document->check();
QVERIFY(document->diagnosticMessages().isEmpty());
QVERIFY(document->translationUnit());
QVERIFY(document->translationUnit()->ast());
QVERIFY(document->globalNamespace());
FindFirstFunctionDefinition find(document->translationUnit());
CPlusPlus::DeclarationAST *functionDefinition = find();
LocalSymbols localSymbols(document, functionDefinition);
const QList<Result> actualUses = Result::fromLocalUses(localSymbols.uses);
// foreach (const Result &result, actualUses)
// qDebug() << QTest::toString(result);
QCOMPARE(actualUses, expectedUses);
}
} // namespace Internal
} // namespace CppTools

View File

@@ -298,8 +298,7 @@ void CppModelManager::ensureUpdated()
return;
m_projectFiles = internalProjectFiles();
m_includePaths = internalIncludePaths();
m_frameworkPaths = internalFrameworkPaths();
m_headerPaths = internalHeaderPaths();
m_definedMacros = internalDefinedMacros();
m_dirty = false;
}
@@ -320,34 +319,23 @@ QStringList CppModelManager::internalProjectFiles() const
return files;
}
QStringList CppModelManager::internalIncludePaths() const
ProjectPart::HeaderPaths CppModelManager::internalHeaderPaths() const
{
QStringList includePaths;
ProjectPart::HeaderPaths headerPaths;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projectToProjectsInfo);
while (it.hasNext()) {
it.next();
const ProjectInfo pinfo = it.value();
foreach (const ProjectPart::Ptr &part, pinfo.projectParts())
foreach (const QString &path, part->includePaths)
includePaths.append(CppSourceProcessor::cleanPath(path));
foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) {
foreach (const ProjectPart::HeaderPath &path, part->headerPaths) {
const ProjectPart::HeaderPath hp(CppSourceProcessor::cleanPath(path.path),
path.type);
if (!headerPaths.contains(hp))
headerPaths += hp;
}
}
}
includePaths.removeDuplicates();
return includePaths;
}
QStringList CppModelManager::internalFrameworkPaths() const
{
QStringList frameworkPaths;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projectToProjectsInfo);
while (it.hasNext()) {
it.next();
const ProjectInfo pinfo = it.value();
foreach (const ProjectPart::Ptr &part, pinfo.projectParts())
foreach (const QString &path, part->frameworkPaths)
frameworkPaths.append(CppSourceProcessor::cleanPath(path));
}
frameworkPaths.removeDuplicates();
return frameworkPaths;
return headerPaths;
}
static void addUnique(const QList<QByteArray> &defs, QByteArray *macros, QSet<QByteArray> *alreadyIn)
@@ -396,7 +384,7 @@ void CppModelManager::dumpModelManagerConfiguration(const QString &logFileId)
dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
dumper.dumpWorkingCopy(workingCopy());
ensureUpdated();
dumper.dumpMergedEntities(m_includePaths, m_frameworkPaths, m_definedMacros);
dumper.dumpMergedEntities(m_headerPaths, m_definedMacros);
}
void CppModelManager::addExtraEditorSupport(AbstractEditorSupport *editorSupport)
@@ -595,8 +583,7 @@ public:
bool configurationChanged() const
{
return definesChanged()
|| m_new.includePaths() != m_old.includePaths()
|| m_new.frameworkPaths() != m_old.frameworkPaths();
|| m_new.headerPaths() != m_old.headerPaths();
}
bool nothingChanged() const
@@ -761,8 +748,7 @@ ProjectPart::Ptr CppModelManager::fallbackProjectPart() const
ProjectPart::Ptr part(new ProjectPart);
part->projectDefines = m_definedMacros;
part->includePaths = m_includePaths;
part->frameworkPaths = m_frameworkPaths;
part->headerPaths = m_headerPaths;
part->cVersion = ProjectPart::C11;
part->cxxVersion = ProjectPart::CXX11;
part->cxxExtensions = ProjectPart::AllExtensions;

View File

@@ -128,22 +128,16 @@ public:
return m_projectFiles;
}
QStringList includePaths()
ProjectPart::HeaderPaths headerPaths()
{
ensureUpdated();
return m_includePaths;
return m_headerPaths;
}
// Use this *only* for auto tests
void setIncludePaths(const QStringList &includePaths)
void setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths)
{
m_includePaths = includePaths;
}
QStringList frameworkPaths()
{
ensureUpdated();
return m_frameworkPaths;
m_headerPaths = headerPaths;
}
QByteArray definedMacros()
@@ -187,8 +181,7 @@ private:
void ensureUpdated();
QStringList internalProjectFiles() const;
QStringList internalIncludePaths() const;
QStringList internalFrameworkPaths() const;
ProjectPart::HeaderPaths internalHeaderPaths() const;
QByteArray internalDefinedMacros() const;
void dumpModelManagerConfiguration(const QString &logFileId);
@@ -210,8 +203,7 @@ private:
// The members below are cached/(re)calculated from the projects and/or their project parts
bool m_dirty;
QStringList m_projectFiles;
QStringList m_includePaths;
QStringList m_frameworkPaths;
ProjectPart::HeaderPaths m_headerPaths;
QByteArray m_definedMacros;
// Editor integration

View File

@@ -220,23 +220,24 @@ void CppToolsPlugin::test_modelmanager_paths_are_clean()
ProjectInfo pi = mm->projectInfo(project);
QCOMPARE(pi.project().data(), project);
typedef ProjectPart::HeaderPath HeaderPath;
ProjectPart::Ptr part(new ProjectPart);
part->cxxVersion = ProjectPart::CXX98;
part->qtVersion = ProjectPart::Qt5;
part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
part->includePaths = QStringList() << testDataDir.includeDir(false);
part->frameworkPaths = QStringList() << testDataDir.frameworksDir(false);
part->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath)
<< HeaderPath(testDataDir.frameworksDir(false), HeaderPath::FrameworkPath);
pi.appendProjectPart(part);
mm->updateProjectInfo(pi);
QStringList includePaths = mm->includePaths();
QCOMPARE(includePaths.size(), 1);
QVERIFY(includePaths.contains(testDataDir.includeDir()));
QStringList frameworkPaths = mm->frameworkPaths();
QCOMPARE(frameworkPaths.size(), 1);
QVERIFY(frameworkPaths.contains(testDataDir.frameworksDir()));
QList<HeaderPath> headerPaths = mm->headerPaths();
QCOMPARE(headerPaths.size(), 2);
QVERIFY(headerPaths.contains(HeaderPath(testDataDir.includeDir(), HeaderPath::IncludePath)));
QVERIFY(headerPaths.contains(HeaderPath(testDataDir.frameworksDir(),
HeaderPath::FrameworkPath)));
}
/// Check: Frameworks headers are resolved.
@@ -254,12 +255,15 @@ void CppToolsPlugin::test_modelmanager_framework_headers()
ProjectInfo pi = mm->projectInfo(project);
QCOMPARE(pi.project().data(), project);
typedef ProjectPart::HeaderPath HeaderPath;
ProjectPart::Ptr part(new ProjectPart);
part->cxxVersion = ProjectPart::CXX98;
part->qtVersion = ProjectPart::Qt5;
part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
part->includePaths << testDataDir.includeDir();
part->frameworkPaths << testDataDir.frameworksDir();
part->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath)
<< HeaderPath(testDataDir.frameworksDir(false), HeaderPath::FrameworkPath);
const QString &source = testDataDir.fileFromSourcesDir(
_("test_modelmanager_framework_headers.cpp"));
part->files << ProjectFile(source, ProjectFile::CXXSource);
@@ -303,11 +307,14 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
ProjectInfo pi = mm->projectInfo(project);
QCOMPARE(pi.project().data(), project);
typedef ProjectPart::HeaderPath HeaderPath;
ProjectPart::Ptr part(new ProjectPart);
part->cxxVersion = ProjectPart::CXX98;
part->qtVersion = ProjectPart::Qt5;
part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
part->includePaths = QStringList() << testDataDir.includeDir(false);
part->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath);
part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
pi.appendProjectPart(part);
@@ -806,6 +813,8 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
Project *project = helper.createProject(_("test_modelmanager_defines_per_project"));
typedef ProjectPart::HeaderPath HeaderPath;
ProjectPart::Ptr part1(new ProjectPart);
part1->projectFile = QLatin1String("project1.projectfile");
part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource));
@@ -813,7 +822,8 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
part1->cxxVersion = ProjectPart::CXX11;
part1->qtVersion = ProjectPart::NoQt;
part1->projectDefines = QByteArray("#define SUB1\n");
part1->includePaths = QStringList() << testDataDirectory.includeDir(false);
part1->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath);
ProjectPart::Ptr part2(new ProjectPart);
part2->projectFile = QLatin1String("project1.projectfile");
@@ -822,7 +832,8 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
part2->cxxVersion = ProjectPart::CXX11;
part2->qtVersion = ProjectPart::NoQt;
part2->projectDefines = QByteArray("#define SUB2\n");
part2->includePaths = QStringList() << testDataDirectory.includeDir(false);
part2->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath);
ProjectInfo pi = mm->projectInfo(project);
pi.appendProjectPart(part1);
@@ -877,6 +888,8 @@ void CppToolsPlugin::test_modelmanager_defines_per_project_pch()
Project *project = helper.createProject(_("test_modelmanager_defines_per_project_pch"));
typedef ProjectPart::HeaderPath HeaderPath;
ProjectPart::Ptr part1(new ProjectPart);
part1->projectFile = QLatin1String("project1.projectfile");
part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource));
@@ -884,7 +897,8 @@ void CppToolsPlugin::test_modelmanager_defines_per_project_pch()
part1->cxxVersion = ProjectPart::CXX11;
part1->qtVersion = ProjectPart::NoQt;
part1->precompiledHeaders.append(pch1File);
part1->includePaths = QStringList() << testDataDirectory.includeDir(false);
part1->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath);
ProjectPart::Ptr part2(new ProjectPart);
part2->projectFile = QLatin1String("project2.projectfile");
@@ -893,7 +907,8 @@ void CppToolsPlugin::test_modelmanager_defines_per_project_pch()
part2->cxxVersion = ProjectPart::CXX11;
part2->qtVersion = ProjectPart::NoQt;
part2->precompiledHeaders.append(pch2File);
part2->includePaths = QStringList() << testDataDirectory.includeDir(false);
part2->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath);
ProjectInfo pi = mm->projectInfo(project);
pi.appendProjectPart(part1);
@@ -949,19 +964,23 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
Project *project = helper.createProject(_("test_modelmanager_defines_per_editor"));
typedef ProjectPart::HeaderPath HeaderPath;
ProjectPart::Ptr part1(new ProjectPart);
part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource));
part1->files.append(ProjectFile(header, ProjectFile::CXXHeader));
part1->cxxVersion = ProjectPart::CXX11;
part1->qtVersion = ProjectPart::NoQt;
part1->includePaths = QStringList() << testDataDirectory.includeDir(false);
part1->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath);
ProjectPart::Ptr part2(new ProjectPart);
part2->files.append(ProjectFile(main2File, ProjectFile::CXXSource));
part2->files.append(ProjectFile(header, ProjectFile::CXXHeader));
part2->cxxVersion = ProjectPart::CXX11;
part2->qtVersion = ProjectPart::NoQt;
part2->includePaths = QStringList() << testDataDirectory.includeDir(false);
part2->headerPaths = QList<HeaderPath>()
<< HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath);
ProjectInfo pi = mm->projectInfo(project);
pi.appendProjectPart(part1);

View File

@@ -154,12 +154,12 @@ void ProjectPart::evaluateToolchain(const ToolChain *tc,
cWarningFlags = tc->warningFlags(cflags);
cxxWarningFlags = tc->warningFlags(cxxflags);
const QList<HeaderPath> headers = tc->systemHeaderPaths(cxxflags, sysRoot);
foreach (const HeaderPath &header, headers)
if (header.kind() == HeaderPath::FrameworkHeaderPath)
frameworkPaths << header.path();
else
includePaths << header.path();
const QList<ProjectExplorer::HeaderPath> headers = tc->systemHeaderPaths(cxxflags, sysRoot);
foreach (const ProjectExplorer::HeaderPath &header, headers) {
headerPaths << HeaderPath(header.path(),
header.kind() == ProjectExplorer::HeaderPath::FrameworkHeaderPath
? HeaderPath::FrameworkPath : HeaderPath::IncludePath);
}
toolchainDefines = tc->predefinedMacros(cxxflags);
}
@@ -187,8 +187,7 @@ CppModelManagerInterface *CppModelManagerInterface::instance()
void CppModelManagerInterface::ProjectInfo::clearProjectParts()
{
m_projectParts.clear();
m_includePaths.clear();
m_frameworkPaths.clear();
m_headerPaths.clear();
m_sourceFiles.clear();
m_defines.clear();
}
@@ -200,17 +199,16 @@ void CppModelManagerInterface::ProjectInfo::appendProjectPart(const ProjectPart:
m_projectParts.append(part);
// Update include paths
QSet<QString> incs = QSet<QString>::fromList(m_includePaths);
foreach (const QString &ins, part->includePaths)
incs.insert(ins);
m_includePaths = incs.toList();
typedef ProjectPart::HeaderPath HeaderPath;
// Update framework paths
QSet<QString> frms = QSet<QString>::fromList(m_frameworkPaths);
foreach (const QString &frm, part->frameworkPaths)
frms.insert(frm);
m_frameworkPaths = frms.toList();
// Update header paths
QSet<HeaderPath> incs = QSet<HeaderPath>::fromList(m_headerPaths);
foreach (const HeaderPath &hp, part->headerPaths) {
if (!incs.contains(hp)) {
incs.insert(hp);
m_headerPaths += hp;
}
}
// Update source files
QSet<QString> srcs = QSet<QString>::fromList(m_sourceFiles);

View File

@@ -101,6 +101,27 @@ public:
typedef QSharedPointer<ProjectPart> Ptr;
struct HeaderPath {
enum Type { InvalidPath, IncludePath, FrameworkPath };
public:
QString path;
Type type;
HeaderPath(): type(InvalidPath) {}
HeaderPath(const QString &path, Type type): path(path), type(type) {}
bool isValid() const { return type != InvalidPath; }
bool isFrameworkPath() const { return type == FrameworkPath; }
bool operator==(const HeaderPath &other) const
{ return path == other.path && type == other.type; }
bool operator!=(const HeaderPath &other) const
{ return !(*this == other); }
};
typedef QList<HeaderPath> HeaderPaths;
public:
QString displayName;
QString projectFile;
@@ -109,8 +130,7 @@ public:
QString projectConfigFile; // currently only used by the Generic Project Manager
QByteArray projectDefines;
QByteArray toolchainDefines;
QStringList includePaths;
QStringList frameworkPaths;
QList<HeaderPath> headerPaths;
QStringList precompiledHeaders;
CVersion cVersion;
CXXVersion cxxVersion;
@@ -120,6 +140,9 @@ public:
ProjectExplorer::ToolChain::WarningFlags cxxWarningFlags;
};
inline uint qHash(const ProjectPart::HeaderPath &key, uint seed = 0)
{ return ((qHash(key.path) << 2) | key.type) ^ seed; }
class CPPTOOLS_EXPORT CppModelManagerInterface : public CPlusPlus::CppModelManagerBase
{
Q_OBJECT
@@ -159,11 +182,8 @@ public:
void clearProjectParts();
void appendProjectPart(const ProjectPart::Ptr &part);
const QStringList includePaths() const
{ return m_includePaths; }
const QStringList frameworkPaths() const
{ return m_frameworkPaths; }
const ProjectPart::HeaderPaths headerPaths() const
{ return m_headerPaths; }
const QStringList sourceFiles() const
{ return m_sourceFiles; }
@@ -175,8 +195,7 @@ public:
QPointer<ProjectExplorer::Project> m_project;
QList<ProjectPart::Ptr> m_projectParts;
// The members below are (re)calculated from the project parts once a part is appended.
QStringList m_includePaths;
QStringList m_frameworkPaths;
ProjectPart::HeaderPaths m_headerPaths;
QStringList m_sourceFiles;
QByteArray m_defines;
};
@@ -266,11 +285,10 @@ public:
virtual void setIndexingSupport(CppTools::CppIndexingSupport *indexingSupport) = 0;
virtual CppIndexingSupport *indexingSupport() = 0;
virtual void setIncludePaths(const QStringList &includePaths) = 0;
virtual void setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths) = 0;
virtual void enableGarbageCollector(bool enable) = 0;
virtual QStringList includePaths() = 0;
virtual QStringList frameworkPaths() = 0;
virtual ProjectPart::HeaderPaths headerPaths() = 0;
virtual QByteArray definedMacros() = 0;
signals:

View File

@@ -57,8 +57,7 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy)
CppModelManager *modelManager
= dynamic_cast<CppModelManager *>(CppModelManagerInterface::instance());
QByteArray configFile = modelManager->codeModelConfiguration();
QStringList includePaths;
QStringList frameworkPaths;
ProjectPart::HeaderPaths headerPaths;
QStringList precompiledHeaders;
QString projectConfigFile;
@@ -72,8 +71,7 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy)
if (m_projectPart) {
configFile += m_projectPart->toolchainDefines;
configFile += m_projectPart->projectDefines;
includePaths = m_projectPart->includePaths;
frameworkPaths = m_projectPart->frameworkPaths;
headerPaths = m_projectPart->headerPaths;
projectConfigFile = m_projectPart->projectConfigFile;
if (m_usePrecompiledHeaders)
precompiledHeaders = m_projectPart->precompiledHeaders;
@@ -91,13 +89,8 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy)
m_editorDefinesChangedSinceLastUpdate = false;
}
if (includePaths != m_includePaths) {
m_includePaths = includePaths;
invalidateSnapshot = true;
}
if (frameworkPaths != m_frameworkPaths) {
m_frameworkPaths = frameworkPaths;
if (headerPaths != m_headerPaths) {
m_headerPaths = headerPaths;
invalidateSnapshot = true;
}
@@ -174,8 +167,7 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy)
globalSnapshot.remove(fileInEditor());
sourceProcessor.setGlobalSnapshot(globalSnapshot);
sourceProcessor.setWorkingCopy(workingCopy);
sourceProcessor.setIncludePaths(m_includePaths);
sourceProcessor.setFrameworkPaths(m_frameworkPaths);
sourceProcessor.setHeaderPaths(m_headerPaths);
sourceProcessor.run(configurationFileName);
if (!m_projectConfigFile.isEmpty())
sourceProcessor.run(m_projectConfigFile);
@@ -218,16 +210,10 @@ Snapshot SnapshotUpdater::snapshot() const
return m_snapshot;
}
QStringList SnapshotUpdater::includePaths() const
ProjectPart::HeaderPaths SnapshotUpdater::headerPaths() const
{
QMutexLocker locker(&m_mutex);
return m_includePaths;
}
QStringList SnapshotUpdater::frameworkPaths() const
{
QMutexLocker locker(&m_mutex);
return m_frameworkPaths;
return m_headerPaths;
}
ProjectPart::Ptr SnapshotUpdater::currentProjectPart() const

View File

@@ -56,8 +56,7 @@ public:
CPlusPlus::Document::Ptr document() const;
CPlusPlus::Snapshot snapshot() const;
QStringList includePaths() const;
QStringList frameworkPaths() const;
ProjectPart::HeaderPaths headerPaths() const;
ProjectPart::Ptr currentProjectPart() const;
void setProjectPart(ProjectPart::Ptr projectPart);
@@ -76,8 +75,7 @@ private:
QByteArray m_configFile;
bool m_editorDefinesChangedSinceLastUpdate;
QByteArray m_editorDefines;
QStringList m_includePaths;
QStringList m_frameworkPaths;
ProjectPart::HeaderPaths m_headerPaths;
QString m_projectConfigFile;
QStringList m_precompiledHeaders;
CPlusPlus::Snapshot m_snapshot;

View File

@@ -6,6 +6,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/textfileformat.h>
#include <QCoreApplication>
@@ -98,38 +99,20 @@ void CppSourceProcessor::setRevision(unsigned revision)
void CppSourceProcessor::setWorkingCopy(const CppModelManagerInterface::WorkingCopy &workingCopy)
{ m_workingCopy = workingCopy; }
void CppSourceProcessor::setIncludePaths(const QStringList &includePaths)
void CppSourceProcessor::setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths)
{
m_includePaths.clear();
m_headerPaths.clear();
for (int i = 0; i < includePaths.size(); ++i) {
const QString &path = includePaths.at(i);
for (int i = 0, ei = headerPaths.size(); i < ei; ++i) {
const ProjectPart::HeaderPath &path = headerPaths.at(i);
if (Utils::HostOsInfo::isMacHost()) {
if (i + 1 < includePaths.size() && path.endsWith(QLatin1String(".framework/Headers"))) {
const QFileInfo pathInfo(path);
const QFileInfo frameworkFileInfo(pathInfo.path());
const QString frameworkName = frameworkFileInfo.baseName();
const QFileInfo nextIncludePath = includePaths.at(i + 1);
if (nextIncludePath.fileName() == frameworkName) {
// We got a QtXXX.framework/Headers followed by $QTDIR/include/QtXXX.
// In this case we prefer to include files from $QTDIR/include/QtXXX.
continue;
}
}
}
m_includePaths.append(cleanPath(path));
if (path.type == ProjectPart::HeaderPath::IncludePath)
m_headerPaths.append(ProjectPart::HeaderPath(cleanPath(path.path), path.type));
else
addFrameworkPath(path);
}
}
void CppSourceProcessor::setFrameworkPaths(const QStringList &frameworkPaths)
{
m_frameworkPaths.clear();
foreach (const QString &frameworkPath, frameworkPaths)
addFrameworkPath(frameworkPath);
}
// Add the given framework path, and expand private frameworks.
//
// Example:
@@ -137,16 +120,19 @@ void CppSourceProcessor::setFrameworkPaths(const QStringList &frameworkPaths)
// has private frameworks in:
// <framework-path>/ApplicationServices.framework/Frameworks
// if the "Frameworks" folder exists inside the top level framework.
void CppSourceProcessor::addFrameworkPath(const QString &frameworkPath)
void CppSourceProcessor::addFrameworkPath(const ProjectPart::HeaderPath &frameworkPath)
{
QTC_ASSERT(frameworkPath.isFrameworkPath(), return);
// The algorithm below is a bit too eager, but that's because we're not getting
// in the frameworks we're linking against. If we would have that, then we could
// add only those private frameworks.
const QString cleanFrameworkPath = cleanPath(frameworkPath);
if (!m_frameworkPaths.contains(cleanFrameworkPath))
m_frameworkPaths.append(cleanFrameworkPath);
const ProjectPart::HeaderPath cleanFrameworkPath(cleanPath(frameworkPath.path),
frameworkPath.type);
if (!m_headerPaths.contains(cleanFrameworkPath))
m_headerPaths.append(cleanFrameworkPath);
const QDir frameworkDir(cleanFrameworkPath);
const QDir frameworkDir(cleanFrameworkPath.path);
const QStringList filter = QStringList() << QLatin1String("*.framework");
foreach (const QFileInfo &framework, frameworkDir.entryInfoList(filter)) {
if (!framework.isDir())
@@ -154,7 +140,8 @@ void CppSourceProcessor::addFrameworkPath(const QString &frameworkPath)
const QFileInfo privateFrameworks(framework.absoluteFilePath(),
QLatin1String("Frameworks"));
if (privateFrameworks.exists() && privateFrameworks.isDir())
addFrameworkPath(privateFrameworks.absoluteFilePath());
addFrameworkPath(ProjectPart::HeaderPath(privateFrameworks.absoluteFilePath(),
frameworkPath.type));
}
}
@@ -259,8 +246,10 @@ QString CppSourceProcessor::resolveFile_helper(const QString &fileName, IncludeT
// searching as if this would be a global include.
}
foreach (const QString &includePath, m_includePaths) {
const QString path = includePath + fileName;
foreach (const ProjectPart::HeaderPath &headerPath, m_headerPaths) {
if (headerPath.isFrameworkPath())
continue;
const QString path = headerPath.path + fileName;
if (m_workingCopy.contains(path) || checkFile(path))
return path;
}
@@ -271,8 +260,10 @@ QString CppSourceProcessor::resolveFile_helper(const QString &fileName, IncludeT
const QString name = frameworkName + QLatin1String(".framework/Headers/")
+ fileName.mid(index + 1);
foreach (const QString &frameworkPath, m_frameworkPaths) {
const QString path = frameworkPath + name;
foreach (const ProjectPart::HeaderPath &headerPath, m_headerPaths) {
if (!headerPath.isFrameworkPath())
continue;
const QString path = headerPath.path + name;
if (checkFile(path))
return path;
}

View File

@@ -40,8 +40,7 @@ public:
void setRevision(unsigned revision);
void setWorkingCopy(const CppTools::CppModelManagerInterface::WorkingCopy &workingCopy);
void setIncludePaths(const QStringList &includePaths);
void setFrameworkPaths(const QStringList &frameworkPaths);
void setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths);
void setTodo(const QStringList &files);
void run(const QString &fileName);
@@ -54,7 +53,7 @@ public:
void setGlobalSnapshot(const CPlusPlus::Snapshot &snapshot) { m_globalSnapshot = snapshot; }
private:
void addFrameworkPath(const QString &frameworkPath);
void addFrameworkPath(const ProjectPart::HeaderPath &frameworkPath);
CPlusPlus::Document::Ptr switchCurrentDocument(CPlusPlus::Document::Ptr doc);
@@ -90,9 +89,8 @@ private:
bool m_dumpFileNameWhileParsing;
CPlusPlus::Environment m_env;
CPlusPlus::Preprocessor m_preprocess;
QStringList m_includePaths;
ProjectPart::HeaderPaths m_headerPaths;
CppTools::CppModelManagerInterface::WorkingCopy m_workingCopy;
QStringList m_frameworkPaths;
QSet<QString> m_included;
CPlusPlus::Document::Ptr m_currentDoc;
QSet<QString> m_todo;

View File

@@ -71,7 +71,9 @@ public:
QScopedPointer<CppSourceProcessor> sourceProcessor(
CppModelManager::createSourceProcessor());
sourceProcessor->setIncludePaths(QStringList(TestIncludePaths::directoryOfTestFile()));
const ProjectPart::HeaderPath hp(TestIncludePaths::directoryOfTestFile(),
ProjectPart::HeaderPath::IncludePath);
sourceProcessor->setHeaderPaths(ProjectPart::HeaderPaths() << hp);
sourceProcessor->run(fileName);
Document::Ptr document = m_cmm->document(fileName);

View File

@@ -128,6 +128,7 @@ equals(TEST, 1) {
cppcodegen_test.cpp \
cppcompletion_test.cpp \
cppheadersource_test.cpp \
cpplocalsymbols_test.cpp \
cpplocatorfilter_test.cpp \
cppmodelmanager_test.cpp \
cpppointerdeclarationformatter_test.cpp \

View File

@@ -87,6 +87,7 @@ QtcPlugin {
"cppcodegen_test.cpp",
"cppcompletion_test.cpp",
"cppheadersource_test.cpp",
"cpplocalsymbols_test.cpp",
"cpplocatorfilter_test.cpp",
"cppmodelmanager_test.cpp",
"cpppointerdeclarationformatter_test.cpp",

View File

@@ -162,6 +162,9 @@ private slots:
void test_typehierarchy_data();
void test_typehierarchy();
void test_cpplocalsymbols_data();
void test_cpplocalsymbols();
void test_includeGroups_detectIncludeGroupsByNewLines();
void test_includeGroups_detectIncludeGroupsByIncludeDir();
void test_includeGroups_detectIncludeGroupsByIncludeType();

View File

@@ -518,7 +518,10 @@ static QList<Include> includesForSource(const QByteArray &source)
CppModelManager *cmm = CppModelManager::instance();
cmm->GC();
QScopedPointer<CppSourceProcessor> sourceProcessor(CppModelManager::createSourceProcessor());
sourceProcessor->setIncludePaths(QStringList(TestIncludePaths::globalIncludePath()));
sourceProcessor->setHeaderPaths(ProjectPart::HeaderPaths()
<< ProjectPart::HeaderPath(
TestIncludePaths::globalIncludePath(),
ProjectPart::HeaderPath::IncludePath));
sourceProcessor->run(fileName);
Document::Ptr document = cmm->document(fileName);

View File

@@ -87,8 +87,7 @@ void ModelManagerTestHelper::verifyClean()
assert(mm);
QVERIFY(mm->projectInfos().isEmpty());
QVERIFY(mm->includePaths().isEmpty());
QVERIFY(mm->frameworkPaths().isEmpty());
QVERIFY(mm->headerPaths().isEmpty());
QVERIFY(mm->definedMacros().isEmpty());
QVERIFY(mm->projectFiles().isEmpty());
QVERIFY(mm->snapshot().isEmpty());

View File

@@ -34,6 +34,7 @@
#include "debuggercore.h"
#include "debuggerengine.h"
#include "debuggerstringutils.h"
#include "simplifytype.h"
#include <extensionsystem/invoker.h>
#include <utils/hostosinfo.h>
@@ -593,7 +594,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
case 1:
if (role == Qt::DisplayRole) {
if (!response.functionName.isEmpty())
return response.functionName;
return simplifyType(response.functionName);
if (!data.functionName.isEmpty())
return data.functionName;
if (data.type == BreakpointAtMain

View File

@@ -184,7 +184,7 @@ QVariantMap DebuggerItem::toMap() const
QVariantMap data;
data.insert(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME), m_displayName);
data.insert(QLatin1String(DEBUGGER_INFORMATION_ID), m_id);
data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toUserOutput());
data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toString());
data.insert(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), int(m_engineType));
data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), m_isAutoDetected);
data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTION_SOURCE), m_autoDetectionSource);

View File

@@ -117,7 +117,7 @@ DebuggerItemManager::DebuggerItemManager(QObject *parent)
: QObject(parent)
{
m_instance = this;
m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebugger"));
m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebuggers"));
connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()),
this, SLOT(saveDebuggers()));
}
@@ -297,6 +297,8 @@ void DebuggerItemManager::readLegacyDebuggers(const FileName &file)
if (fn == QLatin1String("auto"))
continue;
FileName command = FileName::fromUserInput(fn);
if (!command.toFileInfo().exists())
continue;
if (findByCommand(command))
continue;
DebuggerItem item;

View File

@@ -159,7 +159,7 @@ void DebuggerItemConfigWidget::setItem(const DebuggerItem &item)
m_displayNameLineEdit->setEnabled(!item.isAutoDetected());
m_displayNameLineEdit->setText(item.displayName());
m_binaryChooser->setEnabled(!item.isAutoDetected());
m_binaryChooser->setReadOnly(item.isAutoDetected());
m_binaryChooser->setFileName(item.command());
QString text;

View File

@@ -2322,12 +2322,15 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
m_hiddenStopAction->setAction(m_interruptAction);
m_localsAndExpressionsWindow->setShowLocals(false);
} else if (state == DebuggerFinished) {
ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
Project *project = SessionManager::startupProject();
const bool canRun = pe->canRun(project, DebugRunMode);
// We don't want to do anything anymore.
m_interruptAction->setEnabled(false);
m_continueAction->setEnabled(false);
m_exitAction->setEnabled(false);
m_startAction->setEnabled(true);
m_debugWithoutDeployAction->setEnabled(true);
m_startAction->setEnabled(canRun);
m_debugWithoutDeployAction->setEnabled(canRun);
setProxyAction(m_visibleStartAction, Core::Id(Constants::DEBUG));
m_hiddenStopAction->setAction(m_undisturbableAction);
m_codeModelSnapshot = CPlusPlus::Snapshot();

Some files were not shown because too many files have changed in this diff Show More