summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Shcherbakov <ivan@sysprogs.com>2017-06-20 21:13:01 (GMT)
committerBrad King <brad.king@kitware.com>2017-07-11 11:50:22 (GMT)
commit0c5723821542a43fa211c73abc08e59e2fd395e2 (patch)
tree9d2b7568a58789e5d275bcc7ef5b1feade24fe4c
parent4db32275149e2a68c74d2abf5158ee29976b7300 (diff)
downloadCMake-0c5723821542a43fa211c73abc08e59e2fd395e2.zip
CMake-0c5723821542a43fa211c73abc08e59e2fd395e2.tar.gz
CMake-0c5723821542a43fa211c73abc08e59e2fd395e2.tar.bz2
server: Report backtraces in codemodel response
Report the source locations (e.g. in `CMakeLists.txt`) for all targets and target-related statements. This allows IDEs to locate the statements and automatically edit them when the user adds or removes files or changes target properties via GUI. Increment the protocol minor version number to tell clients that the new information is available.
-rw-r--r--Help/manual/cmake-server.7.rst42
-rw-r--r--Source/cmServerDictionary.h5
-rw-r--r--Source/cmServerProtocol.cxx52
3 files changed, 97 insertions, 2 deletions
diff --git a/Help/manual/cmake-server.7.rst b/Help/manual/cmake-server.7.rst
index 9520cc1..211ebe4 100644
--- a/Help/manual/cmake-server.7.rst
+++ b/Help/manual/cmake-server.7.rst
@@ -496,6 +496,9 @@ Each target object can have the following keys:
with the sysroot path.
"fileGroups"
contains the source files making up the target.
+"crossReferences"
+ contains the location of the target in the corresponding CMakeLists.txt
+ file and the locations of the related statements like "target_link_libraries"
FileGroups are used to group sources using similar settings together.
@@ -521,6 +524,16 @@ Each fileGroup object may contain the following keys:
All file paths in the fileGroup are either absolute or relative to the
sourceDirectory of the target.
+CrossReferences object is used to report the location of the target (including
+the entire call stack if the target is defined in a function) and the related
+"target_link_libraries", "target_include_directories", "target_compile_definitions"
+and "target_compile_options" statements.
+
+See the example below for details on the internal format of the "crossReferences" object.
+Line numbers stated in the "backtrace" entries are 1-based. The last entry of a backtrace
+is a special entry with missing "line" and "name" fields that specifies the initial
+CMakeLists.txt file.
+
Example::
[== "CMake Server" ==[
@@ -557,7 +570,34 @@ CMake will reply::
"linkerLanguage": "C",
"name": "cmForm",
"sourceDirectory": "/home/code/src/cmake/Source/CursesDialog/form",
- "type": "STATIC_LIBRARY"
+ "type": "STATIC_LIBRARY",
+ "crossReferences": {
+ "backtrace": [
+ {
+ "line": 7,
+ "name": "add_executable",
+ "path": "C:/full/path/CMakeLists.txt"
+ },
+ {
+ "path": "c:/full/path/CMakeLists.txt"
+ }
+ ],
+ "relatedStatements": [
+ {
+ "backtrace": [
+ {
+ "line": 8,
+ "name": "target_link_libraries",
+ "path": "c:/full/path/CMakeLists.txt"
+ },
+ {
+ "path": "c:/full/path/CMakeLists.txt"
+ }
+ ],
+ "type": "target_link_libraries"
+ }
+ ]
+ }
}
]
},
diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h
index e6a7ae6..405ff6b 100644
--- a/Source/cmServerDictionary.h
+++ b/Source/cmServerDictionary.h
@@ -89,6 +89,11 @@ static const std::string kWARN_UNUSED_KEY = "warnUnused";
static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
static const std::string kWATCHED_FILES_KEY = "watchedFiles";
+static const std::string kTARGET_CROSS_REFERENCES_KEY = "crossReferences";
+static const std::string kLINE_NUMBER_KEY = "line";
+static const std::string kBACKTRACE_KEY = "backtrace";
+static const std::string kRELATED_STATEMENTS_KEY = "relatedStatements";
+
static const std::string kSTART_MAGIC = "[== \"CMake Server\" ==[";
static const std::string kEND_MAGIC = "]== \"CMake Server\" ==]";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index 54ee109..21b69cf 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -2,12 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmServerProtocol.h"
+#include "cmAlgorithms.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmFileMonitor.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkLineComputer.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmServer.h"
@@ -18,6 +20,7 @@
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cm_uv.h"
#include "cmake.h"
@@ -249,7 +252,7 @@ bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
std::pair<int, int> cmServerProtocol1::ProtocolVersion() const
{
- return std::make_pair(1, 0);
+ return std::make_pair(1, 1);
}
static void setErrorMessage(std::string* errorMessage, const std::string& text)
@@ -729,6 +732,37 @@ static Json::Value DumpSourceFilesList(
return result;
}
+static Json::Value DumpBacktrace(const cmListFileBacktrace& backtrace)
+{
+ Json::Value result = Json::arrayValue;
+
+ cmListFileBacktrace backtraceCopy = backtrace;
+ while (!backtraceCopy.Top().FilePath.empty()) {
+ Json::Value entry = Json::objectValue;
+ entry[kPATH_KEY] = backtraceCopy.Top().FilePath;
+ if (backtraceCopy.Top().Line) {
+ entry[kLINE_NUMBER_KEY] = (int)backtraceCopy.Top().Line;
+ }
+ if (!backtraceCopy.Top().Name.empty()) {
+ entry[kNAME_KEY] = backtraceCopy.Top().Name;
+ }
+ result.append(std::move(entry));
+ backtraceCopy = backtraceCopy.Pop();
+ }
+ return result;
+}
+
+static void DumpBacktraceRange(Json::Value& result, const std::string& type,
+ const cmBacktraceRange& range)
+{
+ for (const auto& bt : range) {
+ Json::Value obj = Json::objectValue;
+ obj[kTYPE_KEY] = type;
+ obj[kBACKTRACE_KEY] = DumpBacktrace(bt);
+ result.append(obj);
+ }
+}
+
static Json::Value DumpTarget(cmGeneratorTarget* target,
const std::string& config)
{
@@ -763,6 +797,22 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
result[kFULL_NAME_KEY] = target->GetFullName(config);
+ Json::Value crossRefs = Json::objectValue;
+ crossRefs[kBACKTRACE_KEY] = DumpBacktrace(target->Target->GetBacktrace());
+
+ Json::Value statements = Json::arrayValue;
+ DumpBacktraceRange(statements, "target_compile_definitions",
+ target->Target->GetCompileDefinitionsBacktraces());
+ DumpBacktraceRange(statements, "target_include_directories",
+ target->Target->GetIncludeDirectoriesBacktraces());
+ DumpBacktraceRange(statements, "target_compile_options",
+ target->Target->GetCompileOptionsBacktraces());
+ DumpBacktraceRange(statements, "target_link_libraries",
+ target->Target->GetLinkImplementationBacktraces());
+
+ crossRefs[kRELATED_STATEMENTS_KEY] = std::move(statements);
+ result[kTARGET_CROSS_REFERENCES_KEY] = std::move(crossRefs);
+
if (target->HaveWellDefinedOutputFiles()) {
Json::Value artifacts = Json::arrayValue;
artifacts.append(