forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/3.5'
Change-Id: I1ce0fa92e5c469d591d3030d1a4f168dcee232ba
This commit is contained in:
Binary file not shown.
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 11 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 7.4 KiB |
@@ -55,19 +55,20 @@
|
|||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
An IDE needs a parser for the language and the semantic analyzes. The only
|
An IDE needs a parser for the language and the semantic analyzes.
|
||||||
difference between a code model and a compiler is that a code model does not
|
|
||||||
generate an executable.
|
|
||||||
|
|
||||||
As \l{http://clang.llvm.org/}{Clang} is a compiler, as well as a code model,
|
\section1 Using Clang Code Model
|
||||||
it provides accurate information. The feedback you get through warning and
|
|
||||||
error markers is the same as the compiler will give you, not an incomplete
|
The \l{http://clang.llvm.org/}{Clang} project provides libraries for parsing
|
||||||
|
C and C++ source files. The feedback you get through warning and
|
||||||
|
error markers is the same as a compiler will give you, not an incomplete
|
||||||
set or a close approximation, as when using the built-in \QC code model.
|
set or a close approximation, as when using the built-in \QC code model.
|
||||||
Clang focuses on detailed information for diagnostics, which is really
|
Clang focuses on detailed information for diagnostics, which is really
|
||||||
useful if the code contains typos, for example.
|
useful if the code contains typos, for example.
|
||||||
|
|
||||||
Also, Clang already supports C++98/03, C89 and C99, Objective-C (and
|
Clang keeps up with the development of the C++ language. At the time of this
|
||||||
Objective-C++), and C++11 support is in active development.
|
writing, it supports C++98/03, C++11, C++14, C89, C99, Objective-C, and
|
||||||
|
Objective-C++.
|
||||||
|
|
||||||
On the downside, for large projects using Clang as code model is slower than
|
On the downside, for large projects using Clang as code model is slower than
|
||||||
using the built-in code model. Clang does not need to generate object files,
|
using the built-in code model. Clang does not need to generate object files,
|
||||||
@@ -84,14 +85,14 @@
|
|||||||
|
|
||||||
\list
|
\list
|
||||||
|
|
||||||
\li Highlighting
|
|
||||||
\li Code completion
|
\li Code completion
|
||||||
|
\li Syntactic and semantic highlighting
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
To use the plugin, you must build it and configure it in \QC.
|
To use the plugin, you must build it and configure it in \QC.
|
||||||
|
|
||||||
\section1 Building Clang Code Model Plugin
|
\section2 Building Clang Code Model Plugin
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
|
|
||||||
@@ -138,7 +139,7 @@
|
|||||||
|
|
||||||
\li Installed via package manager on Linux:
|
\li Installed via package manager on Linux:
|
||||||
|
|
||||||
\c {LLVM_INSTALL_DIR=/usr/lib/llvm-3.4}
|
\c {LLVM_INSTALL_DIR=/usr/lib/llvm-3.6}
|
||||||
|
|
||||||
\li Manually built on Unix in release mode:
|
\li Manually built on Unix in release mode:
|
||||||
|
|
||||||
@@ -154,7 +155,7 @@
|
|||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\section1 Configuring Clang Code Model Plugin
|
\section2 Configuring Clang Code Model Plugin
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
|
|
||||||
|
@@ -168,8 +168,8 @@
|
|||||||
\key {Ctrl+E,F2} to follow the symbol in the next split. If necessary, the
|
\key {Ctrl+E,F2} to follow the symbol in the next split. If necessary, the
|
||||||
view is automatically split. To change the default behavior, select
|
view is automatically split. To change the default behavior, select
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
|
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
|
||||||
\uicontrol Display, and then select
|
\uicontrol Display > \uicontrol {Always open links in another split}.
|
||||||
\uicontrol {Always Open Links in Next Split}. Additional symbols are
|
Additional symbols are
|
||||||
displayed and switching between definition and declaration is done in
|
displayed and switching between definition and declaration is done in
|
||||||
another split. If you change the default behavior, the shortcuts for opening
|
another split. If you change the default behavior, the shortcuts for opening
|
||||||
link targets in the next split are used to open them in the current split.
|
link targets in the next split are used to open them in the current split.
|
||||||
@@ -197,5 +197,5 @@
|
|||||||
|
|
||||||
\QC underlines semantic errors in olive in the C++ code editor. To check the
|
\QC underlines semantic errors in olive in the C++ code editor. To check the
|
||||||
correct paths for includes that are not resolved or that are resolved to the
|
correct paths for includes that are not resolved or that are resolved to the
|
||||||
wrong file, select \uicontrol {Project Parts} > \uicontrol {Include Paths}.
|
wrong file, select \uicontrol {Project Parts} > \uicontrol {Header Paths}.
|
||||||
*/
|
*/
|
||||||
|
@@ -787,9 +787,9 @@
|
|||||||
Select \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor}
|
Select \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor}
|
||||||
> \uicontrol Completion.
|
> \uicontrol Completion.
|
||||||
|
|
||||||
By default, code completion considers only the first letter case-sensitive.
|
By default, code completion does not consider case. To apply full or
|
||||||
To apply full or no case-sensitivity, select the option in the
|
first-letter case-sensitivity, select \uicontrol Full or
|
||||||
\uicontrol {Case-sensitivity} field.
|
\uicontrol {First Letter} in the \uicontrol {Case-sensitivity} field.
|
||||||
|
|
||||||
\section2 Summary of Available Types
|
\section2 Summary of Available Types
|
||||||
|
|
||||||
@@ -1291,7 +1291,8 @@
|
|||||||
|
|
||||||
\section2 Specifying Tabs and Indentation
|
\section2 Specifying Tabs and Indentation
|
||||||
|
|
||||||
You can specify tab policy and tab size in the \uicontrol Typing group. In
|
You can specify tab policy and tab size in the
|
||||||
|
\uicontrol {Tabs and Indentation} group. In
|
||||||
the \uicontrol {Tab policy} field, select whether to use only spaces or
|
the \uicontrol {Tab policy} field, select whether to use only spaces or
|
||||||
only tabs for indentation, or to use a mixture of them.
|
only tabs for indentation, or to use a mixture of them.
|
||||||
|
|
||||||
@@ -1416,7 +1417,7 @@
|
|||||||
\li To search only whole words, select \uicontrol {Whole Words Only}.
|
\li To search only whole words, select \uicontrol {Whole Words Only}.
|
||||||
|
|
||||||
\li To search using regular expressions, select
|
\li To search using regular expressions, select
|
||||||
\uicontrol {Regular Expressions}. Regular expressions used in \QC
|
\uicontrol {Use Regular Expressions}. Regular expressions used in \QC
|
||||||
are modeled on Perl regular expressions. For more information on
|
are modeled on Perl regular expressions. For more information on
|
||||||
using regular expressions, see the documentation for the
|
using regular expressions, see the documentation for the
|
||||||
QRegularExpression Class.
|
QRegularExpression Class.
|
||||||
@@ -1444,7 +1445,7 @@
|
|||||||
|
|
||||||
The \uicontrol {Preserve Case when Replacing} option can be selected to
|
The \uicontrol {Preserve Case when Replacing} option can be selected to
|
||||||
preserve the case of the original text when replacing. This option is not
|
preserve the case of the original text when replacing. This option is not
|
||||||
compatible with the \uicontrol {Regular Expressions} search option, and will
|
compatible with the \uicontrol {Use Regular Expressions} search option, and will
|
||||||
thus be disabled when regular expressions are used. When the option is used,
|
thus be disabled when regular expressions are used. When the option is used,
|
||||||
the case of the occurrence will be conserved, according to the following
|
the case of the occurrence will be conserved, according to the following
|
||||||
rules:
|
rules:
|
||||||
@@ -1469,7 +1470,7 @@
|
|||||||
The locations of search hits, breakpoints, and bookmarks in your document
|
The locations of search hits, breakpoints, and bookmarks in your document
|
||||||
are highlighted on the editor scroll bar. To turn highlighting off, select
|
are highlighted on the editor scroll bar. To turn highlighting off, select
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
|
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
|
||||||
\uicontrol {Highlight search results on the scrollbar}.
|
\uicontrol Display > \uicontrol {Highlight search results on the scrollbar}.
|
||||||
|
|
||||||
\section1 Advanced Search
|
\section1 Advanced Search
|
||||||
|
|
||||||
@@ -2532,8 +2533,8 @@
|
|||||||
|
|
||||||
\li Specify the prefix string.
|
\li Specify the prefix string.
|
||||||
|
|
||||||
\li To show only results matching this filter, select
|
\li To implicitly include the filter even when not typing a prefix as a
|
||||||
\uicontrol {Limit to prefix}.
|
part of the search string, select \uicontrol {Include by default}.
|
||||||
|
|
||||||
\li Specify other available options. For more information, see
|
\li Specify other available options. For more information, see
|
||||||
\l{Adding Web Search Engines}.
|
\l{Adding Web Search Engines}.
|
||||||
@@ -2601,8 +2602,9 @@
|
|||||||
|
|
||||||
\li Specify the prefix string.
|
\li Specify the prefix string.
|
||||||
|
|
||||||
To show only results matching this filter, select
|
To implicitly include the filter even when not typing a prefix
|
||||||
\uicontrol {Limit to prefix}.
|
as a part of the search string, select
|
||||||
|
\uicontrol {Include by default}.
|
||||||
|
|
||||||
\image qtcreator-navigate-customfilter.png
|
\image qtcreator-navigate-customfilter.png
|
||||||
|
|
||||||
|
@@ -50,19 +50,20 @@
|
|||||||
and integrated into \QC. The correct folder to place the plugins depends on
|
and integrated into \QC. The correct folder to place the plugins depends on
|
||||||
whether you use the standalone \QD or the integrated \QD.
|
whether you use the standalone \QD or the integrated \QD.
|
||||||
|
|
||||||
The integrated \QD fetches plugins from the \c {%SDK%\bin\designer} folder
|
The integrated \QD fetches plugins from the \c {\bin\plugins\designer}
|
||||||
on Windows and Linux. For information about how to configure plugins on
|
directory in the \QC installation directory on Windows and Linux. For
|
||||||
OS X, see \l{Configuring Qt Designer Plugins on OS X}.
|
information about how to configure plugins on OS X, see
|
||||||
|
\l{Configuring Qt Designer Plugins on OS X}.
|
||||||
|
|
||||||
To check which plugins
|
To check which plugins were loaded successfully and which failed, choose
|
||||||
were loaded successfully and which failed, choose \uicontrol{Tools > Form Editor >
|
\uicontrol Tools > \uicontrol {Form Editor} >
|
||||||
About Qt Designer Plugins}.
|
\uicontrol {About Qt Designer Plugins}.
|
||||||
|
|
||||||
The standalone \QD is part of the Qt library used for building projects,
|
The standalone \QD is part of the Qt library used for building projects,
|
||||||
located under \c {%SDK%\qt}. Therefore, it fetches plugins from the
|
located in \c {<Qt_version>\<compiler>\bin} in the Qt installation
|
||||||
following folder: \c {%SDK%\qt\plugins\designer}. To check which plugins
|
directory. It fetches plugins from the \c {\plugins\designer} subdirectory
|
||||||
were loaded successfully and which failed, choose \uicontrol{Help >
|
of \c bin. To check which plugins were loaded successfully and which failed,
|
||||||
About Plugins}.
|
choose \uicontrol Help > \uicontrol {About Plugins}.
|
||||||
|
|
||||||
\section2 Configuring Qt Designer Plugins on OS X
|
\section2 Configuring Qt Designer Plugins on OS X
|
||||||
|
|
||||||
|
150
scripts/clangCompleteAt.sh
Executable file
150
scripts/clangCompleteAt.sh
Executable file
@@ -0,0 +1,150 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
# * Neither the name of The Qt Company Ltd, nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# --- helpers -----------------------------------------------------------------
|
||||||
|
|
||||||
|
printUsage()
|
||||||
|
{
|
||||||
|
echo "Usage: $0 [-v] [-c clang-executable] file line column"
|
||||||
|
echo
|
||||||
|
echo "Options:"
|
||||||
|
echo " -v Run c-index-test instead of clang to get more details."
|
||||||
|
echo " -c clang-executable Use the provided clang-executable."
|
||||||
|
echo
|
||||||
|
echo "The clang executable is determined by this order:"
|
||||||
|
echo " 1. Use clang from the -c option."
|
||||||
|
echo " 2. Use clang from environment variable CLANG_FOR_COMPLETION."
|
||||||
|
echo " 3. Use clang from \$PATH."
|
||||||
|
echo
|
||||||
|
echo "Path to c-index-test will be determined with the help of the clang executable."
|
||||||
|
}
|
||||||
|
|
||||||
|
# There is no readlink on cygwin.
|
||||||
|
hasReadLink()
|
||||||
|
{
|
||||||
|
return $(command -v readlink >/dev/null 2>&1)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkIfFileExistsOrDie()
|
||||||
|
{
|
||||||
|
[ ! -f "$1" ] && echo "'$1' is not a file or does not exist." && exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
checkIfFileExistsAndIsExecutableOrDie()
|
||||||
|
{
|
||||||
|
checkIfFileExistsOrDie "$1"
|
||||||
|
[ ! -x "$1" ] && echo "'$1' is not executable." && exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
findClangOrDie()
|
||||||
|
{
|
||||||
|
if [ -z "$CLANG_EXEC" ]; then
|
||||||
|
if [ -n "${CLANG_FOR_COMPLETION}" ]; then
|
||||||
|
CLANG_EXEC=${CLANG_FOR_COMPLETION}
|
||||||
|
else
|
||||||
|
CLANG_EXEC=$(which clang)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
hasReadLink && CLANG_EXEC=$(readlink -e "$CLANG_EXEC")
|
||||||
|
checkIfFileExistsAndIsExecutableOrDie "$CLANG_EXEC"
|
||||||
|
}
|
||||||
|
|
||||||
|
findCIndexTestOrDie()
|
||||||
|
{
|
||||||
|
if [ -n "$RUN_WITH_CINDEXTEST" ]; then
|
||||||
|
CINDEXTEST_EXEC=$(echo $CLANG_EXEC | sed -e 's/clang/c-index-test/g')
|
||||||
|
hasReadLink && CINDEXTEST_EXEC=$(readlink -e "$CINDEXTEST_EXEC")
|
||||||
|
checkIfFileExistsAndIsExecutableOrDie "$CINDEXTEST_EXEC"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
printClangVersion()
|
||||||
|
{
|
||||||
|
command="${CLANG_EXEC} --version"
|
||||||
|
echo "Command: $command"
|
||||||
|
eval $command
|
||||||
|
}
|
||||||
|
|
||||||
|
runCodeCompletion()
|
||||||
|
{
|
||||||
|
if [ -n "${CINDEXTEST_EXEC}" ]; then
|
||||||
|
command="${CINDEXTEST_EXEC} -code-completion-at=${FILE}:${LINE}:${COLUMN} ${FILE}"
|
||||||
|
else
|
||||||
|
command="${CLANG_EXEC} -cc1 -code-completion-at ${FILE}:${LINE}:${COLUMN} ${FILE}"
|
||||||
|
fi
|
||||||
|
echo "Command: $command"
|
||||||
|
eval $command
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Process arguments -------------------------------------------------------
|
||||||
|
|
||||||
|
CLANG_EXEC=
|
||||||
|
RUN_WITH_CINDEXTEST=
|
||||||
|
|
||||||
|
FILE=
|
||||||
|
LINE=
|
||||||
|
COLUMN=
|
||||||
|
|
||||||
|
while [ -n "$1" ]; do
|
||||||
|
param=$1
|
||||||
|
shift
|
||||||
|
case $param in
|
||||||
|
-h | -help | --help)
|
||||||
|
printUsage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-v | -verbose | --verbose)
|
||||||
|
RUN_WITH_CINDEXTEST=1
|
||||||
|
;;
|
||||||
|
-c | -clang | --clang)
|
||||||
|
CLANG_EXEC=$1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[ "$#" -ne 2 ] && printUsage && exit 1
|
||||||
|
checkIfFileExistsOrDie "$param"
|
||||||
|
FILE=$param
|
||||||
|
LINE=$1
|
||||||
|
COLUMN=$2
|
||||||
|
|
||||||
|
# --- main --------------------------------------------------------------------
|
||||||
|
|
||||||
|
findClangOrDie
|
||||||
|
findCIndexTestOrDie
|
||||||
|
|
||||||
|
printClangVersion
|
||||||
|
echo
|
||||||
|
runCodeCompletion
|
||||||
|
|
@@ -56,6 +56,6 @@ QtcProduct {
|
|||||||
Group {
|
Group {
|
||||||
fileTagsFilter: product.type
|
fileTagsFilter: product.type
|
||||||
qbs.install: true
|
qbs.install: true
|
||||||
qbs.installDir: project.ide_app_path
|
qbs.installDir: project.ide_bin_path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -847,7 +847,6 @@ void PluginManagerPrivate::nextDelayedInitialize()
|
|||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) :
|
PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) :
|
||||||
m_failedTests(0),
|
|
||||||
delayedInitializeTimer(0),
|
delayedInitializeTimer(0),
|
||||||
shutdownEventLoop(0),
|
shutdownEventLoop(0),
|
||||||
m_profileElapsedMS(0),
|
m_profileElapsedMS(0),
|
||||||
@@ -1127,6 +1126,7 @@ void PluginManagerPrivate::startTests()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int failedTests = 0;
|
||||||
foreach (const PluginManagerPrivate::TestSpec &testSpec, testSpecs) {
|
foreach (const PluginManagerPrivate::TestSpec &testSpec, testSpecs) {
|
||||||
IPlugin *plugin = testSpec.pluginSpec->plugin();
|
IPlugin *plugin = testSpec.pluginSpec->plugin();
|
||||||
if (!plugin)
|
if (!plugin)
|
||||||
@@ -1144,10 +1144,10 @@ void PluginManagerPrivate::startTests()
|
|||||||
? generateCompleteTestPlan(plugin, testObjects)
|
? generateCompleteTestPlan(plugin, testObjects)
|
||||||
: generateCustomTestPlan(plugin, testObjects, testSpec.testFunctionsOrObjects);
|
: generateCustomTestPlan(plugin, testObjects, testSpec.testFunctionsOrObjects);
|
||||||
|
|
||||||
m_failedTests += executeTestPlan(testPlan);
|
failedTests += executeTestPlan(testPlan);
|
||||||
}
|
}
|
||||||
if (!testSpecs.isEmpty())
|
|
||||||
QTimer::singleShot(1, this, SLOT(exitWithNumberOfFailedTests()));
|
QTimer::singleShot(0, this, [failedTests]() { emit m_instance->testsFinished(failedTests); });
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1270,14 +1270,6 @@ void PluginManagerPrivate::asyncShutdownFinished()
|
|||||||
shutdownEventLoop->exit();
|
shutdownEventLoop->exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
*/
|
|
||||||
void PluginManagerPrivate::exitWithNumberOfFailedTests()
|
|
||||||
{
|
|
||||||
QCoreApplication::exit(m_failedTests);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
|
@@ -158,6 +158,7 @@ signals:
|
|||||||
|
|
||||||
void pluginsChanged();
|
void pluginsChanged();
|
||||||
void initializationDone();
|
void initializationDone();
|
||||||
|
void testsFinished(int failedTests);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void remoteArguments(const QString &serializedArguments, QObject *socket);
|
void remoteArguments(const QString &serializedArguments, QObject *socket);
|
||||||
|
@@ -102,7 +102,6 @@ public:
|
|||||||
QHash<QString, PluginCollection *> pluginCategories;
|
QHash<QString, PluginCollection *> pluginCategories;
|
||||||
QList<PluginSpec *> pluginSpecs;
|
QList<PluginSpec *> pluginSpecs;
|
||||||
QList<TestSpec> testSpecs;
|
QList<TestSpec> testSpecs;
|
||||||
int m_failedTests;
|
|
||||||
QStringList pluginPaths;
|
QStringList pluginPaths;
|
||||||
QString pluginIID;
|
QString pluginIID;
|
||||||
QList<QObject *> allObjects; // ### make this a QList<QPointer<QObject> > > ?
|
QList<QObject *> allObjects; // ### make this a QList<QPointer<QObject> > > ?
|
||||||
@@ -138,7 +137,6 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void nextDelayedInitialize();
|
void nextDelayedInitialize();
|
||||||
void asyncShutdownFinished();
|
void asyncShutdownFinished();
|
||||||
void exitWithNumberOfFailedTests();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PluginCollection *defaultCollection;
|
PluginCollection *defaultCollection;
|
||||||
|
@@ -440,6 +440,8 @@ Import LinkPrivate::importNonFile(Document::Ptr doc, const ImportInfo &importInf
|
|||||||
"Import paths:\n"
|
"Import paths:\n"
|
||||||
"%1\n\n"
|
"%1\n\n"
|
||||||
"For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n"
|
"For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n"
|
||||||
|
"For qbs projects, declare and set a qmlImportPaths property in your product "
|
||||||
|
"to add import paths.\n"
|
||||||
"For qmlproject projects, use the importPaths property to add import paths.").arg(
|
"For qmlproject projects, use the importPaths property to add import paths.").arg(
|
||||||
importPaths.join(QLatin1Char('\n'))));
|
importPaths.join(QLatin1Char('\n'))));
|
||||||
}
|
}
|
||||||
|
@@ -1,59 +1 @@
|
|||||||
The ClangCodeModel plugin
|
See ../../../doc/src/editors/creator-clang-codemodel.qdoc
|
||||||
=========================
|
|
||||||
|
|
||||||
The ClangCodeModel plugin integrates the clang frontend into Qt Creator. Clang
|
|
||||||
is "a C language family frontend for LLVM". You can find more information at
|
|
||||||
http://clang.llvm.org/.
|
|
||||||
|
|
||||||
At the time of writing the plugin can replace the following functionality of
|
|
||||||
the built-in code model:
|
|
||||||
* Highlighting
|
|
||||||
* Completion
|
|
||||||
|
|
||||||
All other functionality relies on the built-in code model (indexing, quick
|
|
||||||
fixes, follow symbol, find usages, ...).
|
|
||||||
|
|
||||||
Setup
|
|
||||||
=====
|
|
||||||
|
|
||||||
Compile the plugin
|
|
||||||
------------------
|
|
||||||
|
|
||||||
1. Get libclang
|
|
||||||
|
|
||||||
You need to have libclang (and thus llvm) installed on your system. Either
|
|
||||||
build llvm/clang yourself [1], install some ready-to-use package [2] or use the
|
|
||||||
package manager of your system.
|
|
||||||
|
|
||||||
[1] http://clang.llvm.org/get_started.html
|
|
||||||
See http://llvm.org/docs/GettingStarted.html#git-mirror for git mirrors.
|
|
||||||
[2] http://llvm.org/releases/ or http://llvm.org/builds/
|
|
||||||
|
|
||||||
If you are building llvm/clang yourself, make sure to build it in release mode.
|
|
||||||
|
|
||||||
2. Set LLVM_INSTALL_DIR and (re)build Qt Creator
|
|
||||||
|
|
||||||
Point the LLVM_INSTALL_DIR variable to the build/installation directory of
|
|
||||||
llvm, e.g.:
|
|
||||||
|
|
||||||
Installed via package manager on GNU/Linux:
|
|
||||||
LLVM_INSTALL_DIR=/usr/lib/llvm-3.4
|
|
||||||
Manually build on Unix in release mode:
|
|
||||||
LLVM_INSTALL_DIR=$HOME/llvm-build/Release+Asserts
|
|
||||||
Installed a snapshot on Windows:
|
|
||||||
LLVM_INSTALL_DIR=C:\llvm
|
|
||||||
|
|
||||||
Set the variable either as part of the build environment or pass it directly to
|
|
||||||
qmake and rebuild Qt Creator.
|
|
||||||
|
|
||||||
Enable the plugin
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Enable the "ClangCodeModel" plugin in the dialog "Menu: Help -> About Plugins"
|
|
||||||
and restart Qt Creator.
|
|
||||||
|
|
||||||
Select the file types you want to use the ClangCodeModel for in "Menu: Tools ->
|
|
||||||
Options -> C++ -> Tab: Code Model". For the next opened file matching the
|
|
||||||
selected file types the ClangCodeModel will be used (see limitations at the
|
|
||||||
start of this README).
|
|
||||||
|
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QRegExp>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
@@ -147,7 +148,17 @@ private:
|
|||||||
|
|
||||||
bool excludeHeaderPath(const QString &path) const override
|
bool excludeHeaderPath(const QString &path) const override
|
||||||
{
|
{
|
||||||
return path.contains(QLatin1String("lib/gcc/i686-apple-darwin"));
|
if (path.contains(QLatin1String("lib/gcc/i686-apple-darwin")))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// We already provide a custom clang include path matching the used libclang version,
|
||||||
|
// so better ignore the clang include paths from the system as this might lead to an
|
||||||
|
// unfavorable order with regard to include_next.
|
||||||
|
static QRegExp clangIncludeDir(QLatin1String(".*/lib/clang/\\d+\\.\\d+\\.\\d+/include"));
|
||||||
|
if (clangIncludeDir.exactMatch(path))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addResourceDirOptions()
|
void addResourceDirOptions()
|
||||||
|
@@ -79,6 +79,16 @@ void CompletionChunksToTextConverter::setAddExtraVerticalSpaceBetweenBraces(bool
|
|||||||
m_addExtraVerticalSpaceBetweenBraces = addExtraVerticalSpaceBetweenBraces;
|
m_addExtraVerticalSpaceBetweenBraces = addExtraVerticalSpaceBetweenBraces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompletionChunksToTextConverter::setAddHtmlTags(bool addHtmlTags)
|
||||||
|
{
|
||||||
|
m_addHtmlTags = addHtmlTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompletionChunksToTextConverter::setAddOptional(bool addOptional)
|
||||||
|
{
|
||||||
|
m_addOptional = addOptional;
|
||||||
|
}
|
||||||
|
|
||||||
const QString &CompletionChunksToTextConverter::text() const
|
const QString &CompletionChunksToTextConverter::text() const
|
||||||
{
|
{
|
||||||
return m_text;
|
return m_text;
|
||||||
@@ -99,6 +109,7 @@ QString CompletionChunksToTextConverter::convertToFunctionSignature(const ClangB
|
|||||||
CompletionChunksToTextConverter converter;
|
CompletionChunksToTextConverter converter;
|
||||||
converter.setAddPlaceHolderText(true);
|
converter.setAddPlaceHolderText(true);
|
||||||
converter.setAddResultType(true);
|
converter.setAddResultType(true);
|
||||||
|
converter.setAddOptional(true);
|
||||||
|
|
||||||
converter.parseChunks(codeCompletionChunks);
|
converter.parseChunks(codeCompletionChunks);
|
||||||
|
|
||||||
@@ -120,6 +131,9 @@ QString CompletionChunksToTextConverter::convertToToolTip(const ClangBackEnd::Co
|
|||||||
converter.setAddPlaceHolderText(true);
|
converter.setAddPlaceHolderText(true);
|
||||||
converter.setAddSpaces(true);
|
converter.setAddSpaces(true);
|
||||||
converter.setAddExtraVerticalSpaceBetweenBraces(true);
|
converter.setAddExtraVerticalSpaceBetweenBraces(true);
|
||||||
|
converter.setAddOptional(true);
|
||||||
|
converter.setAddHtmlTags(true);
|
||||||
|
converter.setAddResultType(true);
|
||||||
|
|
||||||
converter.parseChunks(codeCompletionChunks);
|
converter.parseChunks(codeCompletionChunks);
|
||||||
|
|
||||||
@@ -158,11 +172,15 @@ void CompletionChunksToTextConverter::parseText(const Utf8String &text)
|
|||||||
|
|
||||||
void CompletionChunksToTextConverter::parseOptional(const ClangBackEnd::CodeCompletionChunk &optionalCodeCompletionChunk)
|
void CompletionChunksToTextConverter::parseOptional(const ClangBackEnd::CodeCompletionChunk &optionalCodeCompletionChunk)
|
||||||
{
|
{
|
||||||
|
if (m_addOptional) {
|
||||||
|
if (m_addHtmlTags)
|
||||||
m_text += QStringLiteral("<i>");
|
m_text += QStringLiteral("<i>");
|
||||||
|
|
||||||
m_text += convertToFunctionSignature(optionalCodeCompletionChunk.optionalChunks());
|
m_text += convertToFunctionSignature(optionalCodeCompletionChunk.optionalChunks());
|
||||||
|
|
||||||
|
if (m_addHtmlTags)
|
||||||
m_text += QStringLiteral("</i>");
|
m_text += QStringLiteral("</i>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompletionChunksToTextConverter::parsePlaceHolder(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
|
void CompletionChunksToTextConverter::parsePlaceHolder(const ClangBackEnd::CodeCompletionChunk &codeCompletionChunk)
|
||||||
|
@@ -52,6 +52,8 @@ public:
|
|||||||
void setAddResultType(bool addResultType);
|
void setAddResultType(bool addResultType);
|
||||||
void setAddSpaces(bool addSpaces);
|
void setAddSpaces(bool addSpaces);
|
||||||
void setAddExtraVerticalSpaceBetweenBraces(bool addExtraVerticalSpaceBetweenBraces);
|
void setAddExtraVerticalSpaceBetweenBraces(bool addExtraVerticalSpaceBetweenBraces);
|
||||||
|
void setAddHtmlTags(bool addHtmlTags);
|
||||||
|
void setAddOptional(bool addOptional);
|
||||||
|
|
||||||
const QString &text() const;
|
const QString &text() const;
|
||||||
const std::vector<int> &placeholderPositions() const;
|
const std::vector<int> &placeholderPositions() const;
|
||||||
@@ -83,6 +85,8 @@ private:
|
|||||||
bool m_addResultType = false;
|
bool m_addResultType = false;
|
||||||
bool m_addSpaces = false;
|
bool m_addSpaces = false;
|
||||||
bool m_addExtraVerticalSpaceBetweenBraces = false;
|
bool m_addExtraVerticalSpaceBetweenBraces = false;
|
||||||
|
bool m_addHtmlTags = false;
|
||||||
|
bool m_addOptional = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -868,8 +868,8 @@ void ClangCodeCompletionTest::testCompleteFunctions()
|
|||||||
QVERIFY(hasItem(t.proposal, "void f()"));
|
QVERIFY(hasItem(t.proposal, "void f()"));
|
||||||
QVERIFY(hasItem(t.proposal, "void f(int a)"));
|
QVERIFY(hasItem(t.proposal, "void f(int a)"));
|
||||||
QVERIFY(hasItem(t.proposal, "void f(const QString &s)"));
|
QVERIFY(hasItem(t.proposal, "void f(const QString &s)"));
|
||||||
QVERIFY(hasItem(t.proposal, "void f(char c<i>, int optional</i>)")); // TODO: No default argument?
|
QVERIFY(hasItem(t.proposal, "void f(char c, int optional)")); // TODO: No default argument?
|
||||||
QVERIFY(hasItem(t.proposal, "void f(char c<i>, int optional1, int optional2</i>)")); // TODO: No default argument?
|
QVERIFY(hasItem(t.proposal, "void f(char c, int optional1, int optional2)")); // TODO: No default argument?
|
||||||
QVERIFY(hasItem(t.proposal, "void f(const TType<QString> *t)"));
|
QVERIFY(hasItem(t.proposal, "void f(const TType<QString> *t)"));
|
||||||
QVERIFY(hasItem(t.proposal, "TType<QString> f(bool)"));
|
QVERIFY(hasItem(t.proposal, "TType<QString> f(bool)"));
|
||||||
}
|
}
|
||||||
|
@@ -323,6 +323,10 @@ ICore::ICore(MainWindow *mainwindow)
|
|||||||
// Save settings once after all plugins are initialized:
|
// Save settings once after all plugins are initialized:
|
||||||
connect(PluginManager::instance(), SIGNAL(initializationDone()),
|
connect(PluginManager::instance(), SIGNAL(initializationDone()),
|
||||||
this, SLOT(saveSettings()));
|
this, SLOT(saveSettings()));
|
||||||
|
connect(PluginManager::instance(), &PluginManager::testsFinished, [this] (int failedTests) {
|
||||||
|
emit coreAboutToClose();
|
||||||
|
QCoreApplication::exit(failedTests);
|
||||||
|
});
|
||||||
connect(m_mainwindow, SIGNAL(newItemDialogRunningChanged()),
|
connect(m_mainwindow, SIGNAL(newItemDialogRunningChanged()),
|
||||||
this, SIGNAL(newItemDialogRunningChanged()));
|
this, SIGNAL(newItemDialogRunningChanged()));
|
||||||
}
|
}
|
||||||
|
@@ -100,7 +100,7 @@ bool DirectoryFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
|
|||||||
m_ui.prefixLabel->setText(ILocatorFilter::msgPrefixLabel());
|
m_ui.prefixLabel->setText(ILocatorFilter::msgPrefixLabel());
|
||||||
m_ui.prefixLabel->setToolTip(ILocatorFilter::msgPrefixToolTip());
|
m_ui.prefixLabel->setToolTip(ILocatorFilter::msgPrefixToolTip());
|
||||||
m_ui.defaultFlag->setText(ILocatorFilter::msgIncludeByDefault());
|
m_ui.defaultFlag->setText(ILocatorFilter::msgIncludeByDefault());
|
||||||
m_ui.defaultFlag->setText(ILocatorFilter::msgIncludeByDefaultToolTip());
|
m_ui.defaultFlag->setToolTip(ILocatorFilter::msgIncludeByDefaultToolTip());
|
||||||
connect(m_ui.addButton, &QPushButton::clicked,
|
connect(m_ui.addButton, &QPushButton::clicked,
|
||||||
this, &DirectoryFilter::addDirectory, Qt::DirectConnection);
|
this, &DirectoryFilter::addDirectory, Qt::DirectConnection);
|
||||||
connect(m_ui.editButton, &QPushButton::clicked,
|
connect(m_ui.editButton, &QPushButton::clicked,
|
||||||
|
@@ -230,6 +230,9 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
|
|||||||
const QString toolchainPrefix = extractToolchainPrefix(&compilerName);
|
const QString toolchainPrefix = extractToolchainPrefix(&compilerName);
|
||||||
if (!toolchainPrefix.isEmpty())
|
if (!toolchainPrefix.isEmpty())
|
||||||
data.insert(QLatin1String(CPP_TOOLCHAINPREFIX), toolchainPrefix);
|
data.insert(QLatin1String(CPP_TOOLCHAINPREFIX), toolchainPrefix);
|
||||||
|
if (toolchain.contains(QLatin1String("msvc")))
|
||||||
|
data.insert(QLatin1String(CPP_COMPILERNAME), compilerName);
|
||||||
|
else
|
||||||
data.insert(QLatin1String(CPP_CXXCOMPILERNAME), compilerName);
|
data.insert(QLatin1String(CPP_CXXCOMPILERNAME), compilerName);
|
||||||
if (targetAbi.os() != ProjectExplorer::Abi::WindowsOS
|
if (targetAbi.os() != ProjectExplorer::Abi::WindowsOS
|
||||||
|| targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor) {
|
|| targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor) {
|
||||||
@@ -237,6 +240,13 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
|
|||||||
}
|
}
|
||||||
data.insert(QLatin1String(CPP_TOOLCHAINPATH), cxxFileInfo.absolutePath());
|
data.insert(QLatin1String(CPP_TOOLCHAINPATH), cxxFileInfo.absolutePath());
|
||||||
|
|
||||||
|
// TODO: Remove this once compiler version properties are set for MSVC
|
||||||
|
if (targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2013Flavor
|
||||||
|
|| targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2015Flavor) {
|
||||||
|
const QLatin1String flags("/FS");
|
||||||
|
data.insert(QLatin1String(CPP_PLATFORMCFLAGS), flags);
|
||||||
|
data.insert(QLatin1String(CPP_PLATFORMCXXFLAGS), flags);
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,8 +41,11 @@ const char QBS_ARCHITECTURE[] = "qbs.architecture";
|
|||||||
const char QBS_TOOLCHAIN[] = "qbs.toolchain";
|
const char QBS_TOOLCHAIN[] = "qbs.toolchain";
|
||||||
const char CPP_TOOLCHAINPATH[] = "cpp.toolchainInstallPath";
|
const char CPP_TOOLCHAINPATH[] = "cpp.toolchainInstallPath";
|
||||||
const char CPP_TOOLCHAINPREFIX[] = "cpp.toolchainPrefix";
|
const char CPP_TOOLCHAINPREFIX[] = "cpp.toolchainPrefix";
|
||||||
|
const char CPP_COMPILERNAME[] = "cpp.compilerName";
|
||||||
const char CPP_CXXCOMPILERNAME[] = "cpp.cxxCompilerName";
|
const char CPP_CXXCOMPILERNAME[] = "cpp.cxxCompilerName";
|
||||||
const char CPP_LINKERNAME[] = "cpp.linkerName";
|
const char CPP_LINKERNAME[] = "cpp.linkerName";
|
||||||
|
const char CPP_PLATFORMCFLAGS[] = "cpp.platformCFlags";
|
||||||
|
const char CPP_PLATFORMCXXFLAGS[] = "cpp.platformCxxFlags";
|
||||||
const char CPP_PLATFORMPATH[] = "cpp.platformPath";
|
const char CPP_PLATFORMPATH[] = "cpp.platformPath";
|
||||||
const char CPP_XCODESDKNAME[] = "cpp.xcodeSdkName";
|
const char CPP_XCODESDKNAME[] = "cpp.xcodeSdkName";
|
||||||
const char CPP_XCODESDKVERSION[] = "cpp.xcodeSdkVersion";
|
const char CPP_XCODESDKVERSION[] = "cpp.xcodeSdkVersion";
|
||||||
|
@@ -858,6 +858,13 @@ void QbsProject::updateQmlJsCodeModel()
|
|||||||
|
|
||||||
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
||||||
modelManager->defaultProjectInfoForProject(this);
|
modelManager->defaultProjectInfoForProject(this);
|
||||||
|
foreach (const qbs::ProductData &product, m_projectData.allProducts()) {
|
||||||
|
static const QString propertyName = QLatin1String("qmlImportPaths");
|
||||||
|
foreach (const QString &path, product.properties().value(propertyName).toStringList()) {
|
||||||
|
projectInfo.importPaths.maybeInsert(Utils::FileName::fromString(path),
|
||||||
|
QmlJS::Dialect::Qml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setProjectLanguage(ProjectExplorer::Constants::LANG_QMLJS, !projectInfo.sourceFiles.isEmpty());
|
setProjectLanguage(ProjectExplorer::Constants::LANG_QMLJS, !projectInfo.sourceFiles.isEmpty());
|
||||||
modelManager->updateProjectInfo(projectInfo, this);
|
modelManager->updateProjectInfo(projectInfo, this);
|
||||||
|
@@ -366,7 +366,7 @@ TEST_F(CodeCompletionsExtractor, Enumerator)
|
|||||||
CodeCompletion::Available));
|
CodeCompletion::Available));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CodeCompletionsExtractor, Constructor)
|
TEST_F(CodeCompletionsExtractor, DISABLED_Constructor)
|
||||||
{
|
{
|
||||||
ClangCodeCompleteResults completeResults(getResults(constructorTranslationUnit, 20));
|
ClangCodeCompleteResults completeResults(getResults(constructorTranslationUnit, 20));
|
||||||
|
|
||||||
|
@@ -28,107 +28,200 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "gmock/gmock-matchers.h"
|
|
||||||
#include "gtest-qt-printing.h"
|
|
||||||
|
|
||||||
#include <codecompleter.h>
|
#include <codecompleter.h>
|
||||||
#include <filecontainer.h>
|
#include <filecontainer.h>
|
||||||
|
#include <projectpart.h>
|
||||||
#include <translationunit.h>
|
#include <translationunit.h>
|
||||||
#include <unsavedfiles.h>
|
#include <unsavedfiles.h>
|
||||||
#include <utf8stringvector.h>
|
#include <utf8stringvector.h>
|
||||||
#include <projectpart.h>
|
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gmock/gmock-matchers.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "gtest-qt-printing.h"
|
||||||
|
|
||||||
using ::testing::ElementsAreArray;
|
using ::testing::ElementsAreArray;
|
||||||
using ::testing::Contains;
|
using ::testing::Contains;
|
||||||
using ::testing::AllOf;
|
using ::testing::AllOf;
|
||||||
using ::testing::Not;
|
using ::testing::Not;
|
||||||
|
using ::testing::PrintToString;
|
||||||
|
|
||||||
using ClangBackEnd::CodeCompletion;
|
using ClangBackEnd::CodeCompletion;
|
||||||
using ClangBackEnd::CodeCompleter;
|
using ClangBackEnd::CodeCompleter;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
MATCHER_P2(IsCodeCompletion, text, completionKind,
|
||||||
|
std::string(negation ? "isn't" : "is") + " code completion with text "
|
||||||
|
+ PrintToString(text) + " and kind " + PrintToString(completionKind)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (arg.text() != text) {
|
||||||
|
*result_listener << "text is " + PrintToString(arg.text()) + " and not " + PrintToString(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.completionKind() != completionKind) {
|
||||||
|
*result_listener << "kind is " + PrintToString(arg.completionKind()) + " and not " + PrintToString(completionKind);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class CodeCompleter : public ::testing::Test
|
class CodeCompleter : public ::testing::Test
|
||||||
{
|
{
|
||||||
public:
|
protected:
|
||||||
static void SetUpTestCase();
|
void SetUp();
|
||||||
static void TearDownTestCase();
|
void copyTargetHeaderToTemporaryIncludeDirecory();
|
||||||
|
void copyChangedTargetHeaderToTemporaryIncludeDirecory();
|
||||||
|
static Utf8String readFileContent(const QString &fileName);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static ClangBackEnd::ProjectPart projectPart;
|
QTemporaryDir includeDirectory;
|
||||||
static ClangBackEnd::UnsavedFiles unsavedFiles;
|
QString targetHeaderPath{includeDirectory.path() + QStringLiteral("/complete_target_header.h")};
|
||||||
static ClangBackEnd::TranslationUnit translationUnit;
|
ClangBackEnd::ProjectPart projectPart{Utf8StringLiteral("projectPartId")};
|
||||||
static ClangBackEnd::CodeCompleter completer;
|
ClangBackEnd::UnsavedFiles unsavedFiles;
|
||||||
|
ClangBackEnd::TranslationUnit translationUnit{Utf8StringLiteral(TESTDATA_DIR"/complete_completer_main.cpp"),
|
||||||
|
unsavedFiles,
|
||||||
|
projectPart};
|
||||||
|
ClangBackEnd::CodeCompleter completer{translationUnit};
|
||||||
|
ClangBackEnd::FileContainer unsavedMainFileContainer{translationUnit.filePath(),
|
||||||
|
projectPart.projectPartId(),
|
||||||
|
readFileContent(QStringLiteral("/complete_completer_main_unsaved.cpp")),
|
||||||
|
true};
|
||||||
|
ClangBackEnd::FileContainer unsavedTargetHeaderFileContainer{targetHeaderPath,
|
||||||
|
projectPart.projectPartId(),
|
||||||
|
readFileContent(QStringLiteral("/complete_target_header_unsaved.h")),
|
||||||
|
true};
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangBackEnd::ProjectPart CodeCompleter::projectPart(Utf8StringLiteral("projectPartId"));
|
Utf8String CodeCompleter::readFileContent(const QString &fileName)
|
||||||
ClangBackEnd::UnsavedFiles CodeCompleter::unsavedFiles;
|
|
||||||
ClangBackEnd::TranslationUnit CodeCompleter::translationUnit(Utf8StringLiteral(TESTDATA_DIR"/complete_completer.cpp"), unsavedFiles, projectPart);
|
|
||||||
ClangBackEnd::CodeCompleter CodeCompleter::completer = translationUnit;
|
|
||||||
|
|
||||||
void CodeCompleter::SetUpTestCase()
|
|
||||||
{
|
{
|
||||||
QFile unsavedFileContentFile(QStringLiteral(TESTDATA_DIR) + QStringLiteral("/complete_completer_unsaved.cpp"));
|
QFile readFileContentFile(QStringLiteral(TESTDATA_DIR) + fileName);
|
||||||
unsavedFileContentFile.open(QIODevice::ReadOnly);
|
bool hasOpened = readFileContentFile.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||||
|
|
||||||
const Utf8String unsavedFileContent = Utf8String::fromByteArray(unsavedFileContentFile.readAll());
|
EXPECT_TRUE(hasOpened);
|
||||||
const ClangBackEnd::FileContainer unsavedDataFileContainer(translationUnit.filePath(),
|
|
||||||
projectPart.projectPartId(),
|
|
||||||
unsavedFileContent,
|
|
||||||
true);
|
|
||||||
|
|
||||||
unsavedFiles.createOrUpdate({unsavedDataFileContainer});
|
return Utf8String::fromByteArray(readFileContentFile.readAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeCompleter::TearDownTestCase()
|
void CodeCompleter::copyTargetHeaderToTemporaryIncludeDirecory()
|
||||||
{
|
{
|
||||||
translationUnit.reset();
|
QFile::remove(targetHeaderPath);
|
||||||
completer = ClangBackEnd::CodeCompleter();
|
bool hasCopied = QFile::copy(QStringLiteral(TESTDATA_DIR "/complete_target_header.h"),
|
||||||
|
targetHeaderPath);
|
||||||
|
EXPECT_TRUE(hasCopied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeCompleter::copyChangedTargetHeaderToTemporaryIncludeDirecory()
|
||||||
|
{
|
||||||
|
QFile::remove(targetHeaderPath);
|
||||||
|
bool hasCopied = QFile::copy(QStringLiteral(TESTDATA_DIR "/complete_target_header_changed.h"),
|
||||||
|
targetHeaderPath);
|
||||||
|
EXPECT_TRUE(hasCopied);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeCompleter::SetUp()
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(includeDirectory.isValid());
|
||||||
|
|
||||||
|
Utf8String includePath(QStringLiteral("-I") + includeDirectory.path());
|
||||||
|
projectPart.setArguments({includePath});
|
||||||
|
|
||||||
|
copyTargetHeaderToTemporaryIncludeDirecory();
|
||||||
|
|
||||||
|
translationUnit.cxTranslationUnit(); // initialize translation unit so we check changes
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(CodeCompleter, FunctionInUnsavedFile)
|
TEST_F(CodeCompleter, FunctionInUnsavedFile)
|
||||||
{
|
{
|
||||||
ASSERT_THAT(completer.complete(100, 1),
|
unsavedFiles.createOrUpdate({unsavedMainFileContainer});
|
||||||
AllOf(Contains(CodeCompletion(Utf8StringLiteral("functionWithArguments"),
|
|
||||||
0,
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
AllOf(Contains(IsCodeCompletion(Utf8StringLiteral("FunctionWithArguments"),
|
||||||
CodeCompletion::FunctionCompletionKind)),
|
CodeCompletion::FunctionCompletionKind)),
|
||||||
Contains(CodeCompletion(Utf8StringLiteral("function"),
|
Contains(IsCodeCompletion(Utf8StringLiteral("Function"),
|
||||||
0,
|
|
||||||
CodeCompletion::FunctionCompletionKind)),
|
CodeCompletion::FunctionCompletionKind)),
|
||||||
Contains(CodeCompletion(Utf8StringLiteral("newFunction"),
|
Contains(IsCodeCompletion(Utf8StringLiteral("UnsavedFunction"),
|
||||||
0,
|
|
||||||
CodeCompletion::FunctionCompletionKind)),
|
CodeCompletion::FunctionCompletionKind)),
|
||||||
Contains(CodeCompletion(Utf8StringLiteral("f"),
|
Contains(IsCodeCompletion(Utf8StringLiteral("f"),
|
||||||
0,
|
|
||||||
CodeCompletion::FunctionCompletionKind)),
|
CodeCompletion::FunctionCompletionKind)),
|
||||||
Not(Contains(CodeCompletion(Utf8StringLiteral("otherFunction"),
|
Not(Contains(IsCodeCompletion(Utf8StringLiteral("SavedFunction"),
|
||||||
0,
|
|
||||||
CodeCompletion::FunctionCompletionKind)))));
|
CodeCompletion::FunctionCompletionKind)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CodeCompleter, VariableInUnsavedFile)
|
||||||
|
{
|
||||||
|
unsavedFiles.createOrUpdate({unsavedMainFileContainer});
|
||||||
|
|
||||||
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("VariableInUnsavedFile"),
|
||||||
|
CodeCompletion::VariableCompletionKind)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CodeCompleter, GlobalVariableInUnsavedFile)
|
||||||
|
{
|
||||||
|
unsavedFiles.createOrUpdate({unsavedMainFileContainer});
|
||||||
|
|
||||||
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("GlobalVariableInUnsavedFile"),
|
||||||
|
CodeCompletion::VariableCompletionKind)));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(CodeCompleter, Macro)
|
TEST_F(CodeCompleter, Macro)
|
||||||
{
|
{
|
||||||
ASSERT_THAT(completer.complete(100, 1),
|
unsavedFiles.createOrUpdate({unsavedMainFileContainer});
|
||||||
Contains(CodeCompletion(Utf8StringLiteral("Macro"),
|
|
||||||
0,
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("Macro"),
|
||||||
CodeCompletion::PreProcessorCompletionKind)));
|
CodeCompletion::PreProcessorCompletionKind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CodeCompleter, Keyword)
|
TEST_F(CodeCompleter, Keyword)
|
||||||
{
|
{
|
||||||
ASSERT_THAT(completer.complete(100, 1),
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
Contains(CodeCompletion(Utf8StringLiteral("switch"),
|
Contains(IsCodeCompletion(Utf8StringLiteral("switch"),
|
||||||
0,
|
|
||||||
CodeCompletion::KeywordCompletionKind)));
|
CodeCompletion::KeywordCompletionKind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CodeCompleter, FunctionInIncludedHeader)
|
||||||
|
{
|
||||||
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeader"),
|
||||||
|
CodeCompletion::FunctionCompletionKind)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CodeCompleter, FunctionInUnsavedIncludedHeader)
|
||||||
|
{
|
||||||
|
unsavedFiles.createOrUpdate({unsavedTargetHeaderFileContainer});
|
||||||
|
|
||||||
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeaderUnsaved"),
|
||||||
|
CodeCompletion::FunctionCompletionKind)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CodeCompleter, FunctionInChangedIncludedHeader)
|
||||||
|
{
|
||||||
|
copyChangedTargetHeaderToTemporaryIncludeDirecory();
|
||||||
|
|
||||||
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeaderChanged"),
|
||||||
|
CodeCompletion::FunctionCompletionKind)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CodeCompleter, FunctionInChangedIncludedHeaderWithUnsavedContentInMainFile)
|
||||||
|
{
|
||||||
|
unsavedFiles.createOrUpdate({unsavedMainFileContainer});
|
||||||
|
|
||||||
|
copyChangedTargetHeaderToTemporaryIncludeDirecory();
|
||||||
|
|
||||||
|
ASSERT_THAT(completer.complete(27, 1),
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeaderChanged"),
|
||||||
|
CodeCompletion::FunctionCompletionKind)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -81,6 +81,9 @@ protected:
|
|||||||
CodeCompletionChunk ifName{CodeCompletionChunk::TypedText, Utf8StringLiteral("if")};
|
CodeCompletionChunk ifName{CodeCompletionChunk::TypedText, Utf8StringLiteral("if")};
|
||||||
CodeCompletionChunk horizontalSpace{CodeCompletionChunk::HorizontalSpace, Utf8StringLiteral(" ")};
|
CodeCompletionChunk horizontalSpace{CodeCompletionChunk::HorizontalSpace, Utf8StringLiteral(" ")};
|
||||||
CodeCompletionChunk optional{CodeCompletionChunk::Optional, Utf8String(), {comma, functionArgumentY, comma, functionArgumentZ}};
|
CodeCompletionChunk optional{CodeCompletionChunk::Optional, Utf8String(), {comma, functionArgumentY, comma, functionArgumentZ}};
|
||||||
|
CodeCompletionChunk enableIfT{CodeCompletionChunk::TypedText, Utf8StringLiteral("enable_if_t")};
|
||||||
|
CodeCompletionChunk enableIfTCondition{CodeCompletionChunk::Placeholder, Utf8StringLiteral("_Cond")};
|
||||||
|
CodeCompletionChunk enableIfTType{CodeCompletionChunk::Placeholder, Utf8StringLiteral("_Tp")};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(CompletionChunksToTextConverter, ParseIsClearingText)
|
TEST_F(CompletionChunksToTextConverter, ParseIsClearingText)
|
||||||
@@ -117,12 +120,9 @@ TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithParameters)
|
|||||||
TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithOptionalParameter)
|
TEST_F(CompletionChunksToTextConverter, ConvertFunctionWithOptionalParameter)
|
||||||
{
|
{
|
||||||
CodeCompletionChunks completionChunks({integerResultType, functionName, leftParen, functionArgumentX, optional,rightParen});
|
CodeCompletionChunks completionChunks({integerResultType, functionName, leftParen, functionArgumentX, optional,rightParen});
|
||||||
converter.setAddResultType(true);
|
|
||||||
converter.setAddPlaceHolderText(true);
|
|
||||||
|
|
||||||
converter.parseChunks(completionChunks);
|
ASSERT_THAT(Converter::convertToToolTip(completionChunks),
|
||||||
|
QStringLiteral("int Function (char x<i>, int y, int z</i>)"));
|
||||||
ASSERT_THAT(converter.text(), QStringLiteral("int Function(char x<i>, int y, int z</i>)"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CompletionChunksToTextConverter, ConvertVariable)
|
TEST_F(CompletionChunksToTextConverter, ConvertVariable)
|
||||||
@@ -227,7 +227,6 @@ TEST_F(CompletionChunksToTextConverter, ElseIf)
|
|||||||
statements,
|
statements,
|
||||||
verticalSpace,
|
verticalSpace,
|
||||||
rightBrace});
|
rightBrace});
|
||||||
|
|
||||||
setupConverterForKeywords();
|
setupConverterForKeywords();
|
||||||
|
|
||||||
converter.parseChunks(completionChunks);
|
converter.parseChunks(completionChunks);
|
||||||
@@ -235,6 +234,20 @@ TEST_F(CompletionChunksToTextConverter, ElseIf)
|
|||||||
ASSERT_THAT(converter.text(), QStringLiteral("else if {\n\n}"));
|
ASSERT_THAT(converter.text(), QStringLiteral("else if {\n\n}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CompletionChunksToTextConverter, EnableIfT)
|
||||||
|
{
|
||||||
|
CodeCompletionChunks completionChunks({enableIfT,
|
||||||
|
leftAngle,
|
||||||
|
enableIfTCondition,
|
||||||
|
CodeCompletionChunk(CodeCompletionChunk::Optional, Utf8String(), {comma, enableIfTType}),
|
||||||
|
rightAngle});
|
||||||
|
setupConverterForKeywords();
|
||||||
|
|
||||||
|
converter.parseChunks(completionChunks);
|
||||||
|
|
||||||
|
ASSERT_THAT(converter.text(), QStringLiteral("enable_if_t<>"));
|
||||||
|
}
|
||||||
|
|
||||||
void CompletionChunksToTextConverter::setupConverterForKeywords()
|
void CompletionChunksToTextConverter::setupConverterForKeywords()
|
||||||
{
|
{
|
||||||
converter.setAddPlaceHolderPositions(true);
|
converter.setAddPlaceHolderPositions(true);
|
||||||
|
@@ -1,101 +0,0 @@
|
|||||||
void function()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Foo;
|
|
||||||
void functionWithArguments(int i, char *c, const Foo &ref)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void otherFunction()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void f()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
28
tests/unit/unittest/data/complete_completer_main.cpp
Normal file
28
tests/unit/unittest/data/complete_completer_main.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include "complete_forwarding_header_1.h"
|
||||||
|
|
||||||
|
void Function()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo;
|
||||||
|
void FunctionWithArguments(int i, char *c, const Foo &ref)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SavedFunction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
28
tests/unit/unittest/data/complete_completer_main_unsaved.cpp
Normal file
28
tests/unit/unittest/data/complete_completer_main_unsaved.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include "complete_forwarding_header_2.h"
|
||||||
|
|
||||||
|
void Function()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo;
|
||||||
|
void FunctionWithArguments(int i, char *c, const Foo &ref)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnsavedFunction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Macro
|
||||||
|
|
||||||
|
int GlobalVariableInUnsavedFile;
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
int VariableInUnsavedFile;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,100 +0,0 @@
|
|||||||
void function()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Foo;
|
|
||||||
void functionWithArguments(int i, char *c, const Foo &ref)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void newFunction()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Macro
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void f()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
6
tests/unit/unittest/data/complete_forwarding_header_1.h
Normal file
6
tests/unit/unittest/data/complete_forwarding_header_1.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef COMPLETE_FORWARDING_HEADER_1_H
|
||||||
|
#define COMPLETE_FORWARDING_HEADER_1_H
|
||||||
|
|
||||||
|
#include <complete_target_header.h>
|
||||||
|
|
||||||
|
#endif // COMPLETE_FORWARDING_HEADER_1_H
|
7
tests/unit/unittest/data/complete_forwarding_header_2.h
Normal file
7
tests/unit/unittest/data/complete_forwarding_header_2.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef COMPLETE_FORWARDING_HEADER_2_H
|
||||||
|
#define COMPLETE_FORWARDING_HEADER_2_H
|
||||||
|
|
||||||
|
#include <complete_target_header.h>
|
||||||
|
|
||||||
|
#endif // COMPLETE_FORWARDING_HEADER_2_H
|
||||||
|
|
7
tests/unit/unittest/data/complete_target_header.h
Normal file
7
tests/unit/unittest/data/complete_target_header.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef COMPLETE_TARGET_HEADER_H
|
||||||
|
#define COMPLETE_TARGET_HEADER_H
|
||||||
|
|
||||||
|
void FunctionInIncludedHeader();
|
||||||
|
|
||||||
|
#endif // COMPLETE_TARGET_HEADER_H
|
||||||
|
|
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef COMPLETE_TARGET_HEADER_CHANGED_H
|
||||||
|
#define COMPLETE_TARGET_HEADER_CHANGED_H
|
||||||
|
|
||||||
|
void FunctionInIncludedHeader();
|
||||||
|
void FunctionInIncludedHeaderChanged();
|
||||||
|
|
||||||
|
#endif // COMPLETE_TARGET_HEADER_CHANGED_H
|
||||||
|
|
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef COMPLETE_TARGET_HEADER_UNSAVED_H
|
||||||
|
#define COMPLETE_TARGET_HEADER_UNSAVED_H
|
||||||
|
|
||||||
|
void FunctionInIncludedHeader();
|
||||||
|
void FunctionInIncludedHeaderUnsaved();
|
||||||
|
|
||||||
|
#endif // COMPLETE_TARGET_HEADER_UNSAVED_H
|
||||||
|
|
Reference in New Issue
Block a user