Compare commits
16
Commits
v1.db23.p0
...
v2.db24.p0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49e8458d6d | ||
|
|
f78a7186c1 | ||
|
|
f14a8a0a19 | ||
|
|
2dad29877f | ||
|
|
02647c418c | ||
|
|
5dd33e9ecf | ||
|
|
6a55b81e33 | ||
|
|
24668448f5 | ||
|
|
702330265f | ||
|
|
52635f23f3 | ||
|
|
c4aad954e2 | ||
|
|
3b76c403dc | ||
|
|
b8664ce131 | ||
|
|
495b40ef16 | ||
|
|
4edb7f26ac | ||
|
|
db936766e4 |
+2
-1
@@ -111,7 +111,8 @@ before_deploy:
|
||||
- |
|
||||
cd $TRAVIS_BUILD_DIR
|
||||
|
||||
VERSION=$(head -1 build/version.txt)
|
||||
VERSION=$(head -1 version.txt)
|
||||
VERSION=${VERSION//./_}
|
||||
|
||||
if [[ "$PYTHON_BINDING" == "1" ]]; then
|
||||
PYTHON_VERSION=${PYTHON//.}
|
||||
|
||||
+4
-21
@@ -22,23 +22,11 @@ endif()
|
||||
|
||||
# --- Version ---
|
||||
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
find_package(Git)
|
||||
file (STRINGS "version.txt" VERSION_STRING)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --long
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_VERSION_NUMBER
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else()
|
||||
set(GIT_VERSION_NUMBER "v0.db0.p0-0-a")
|
||||
endif()
|
||||
|
||||
string(REGEX REPLACE "v([0-9]+)\\..*" "\\1" INTERFACE_VERSION "${GIT_VERSION_NUMBER}")
|
||||
string(REGEX REPLACE "v[0-9]+\\.db([0-9]+)\\..*" "\\1" DATABASE_VERSION "${GIT_VERSION_NUMBER}")
|
||||
string(REGEX REPLACE "v[0-9]+\\.db[0-9]+\\.p([0-9]+)-.*" "\\1" PATCH_VERSION "${GIT_VERSION_NUMBER}")
|
||||
set(VERSION_STRING "v${INTERFACE_VERSION}.db${DATABASE_VERSION}.p${PATCH_VERSION}")
|
||||
string(REGEX REPLACE "v([0-9]+)\\..*" "\\1" INTERFACE_VERSION "${VERSION_STRING}")
|
||||
string(REGEX REPLACE "v[0-9]+\\.db([0-9]+)\\..*" "\\1" DATABASE_VERSION "${VERSION_STRING}")
|
||||
string(REGEX REPLACE "v[0-9]+\\.db[0-9]+\\.p([0-9]+).*" "\\1" PATCH_VERSION "${VERSION_STRING}")
|
||||
set(VERSION_STRING_UNDERSCORE "v${INTERFACE_VERSION}_db${DATABASE_VERSION}_p${PATCH_VERSION}")
|
||||
|
||||
message(STATUS "SourcetrailDB Version: ${VERSION_STRING}")
|
||||
@@ -46,11 +34,6 @@ message(STATUS "Interface Version: ${INTERFACE_VERSION}")
|
||||
message(STATUS "Database Version: ${DATABASE_VERSION}")
|
||||
message(STATUS "Patch Version: ${PATCH_VERSION}")
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.txt.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/version.txt"
|
||||
)
|
||||
|
||||
|
||||
# --- Core ---
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Sourcetrail Language Extension Guide
|
||||
|
||||
## First Things First
|
||||
|
||||
Build on the shoulders of giants. There are many language tools and frameworks out there that you can build upon, helping you to get things done much faster:
|
||||
|
||||
Look for a parser that generates an Abstract Syntax Tree (AST) for the language you want to index. The parser can be written in any language, but for parsing programming languages these tools are mostly written in the language they are designed to parse. You will probably use the generated AST to visit certain nodes (e.g. all `function definition` nodes) and store all the useful information to the Sourcetrail database (e.g. a `function` with name `foo` is defined at location `<X:Y>`).
|
||||
|
||||
Having a parser is fine, but it is not enough. When you parse code that contains a function call, the parser may just create a `call expression` node for you. You may even be able to get the name of the called function from the AST node, but the parser certainly will not know where this function is actually defined. And if the indexed code defines two or more functions with the same name, you are in trouble.
|
||||
|
||||
That's why it`s best to have a framework that can resolve this info for you. Just to name a few examples:
|
||||
|
||||
* for Java there is the [JavaParser](https://github.com/javaparser/javaparser) for building the AST and the [JavaSymbolSolver](https://github.com/javaparser/javasymbolsolver) (now integrated into JavaParser) for resolving these references.
|
||||
* for C/C++ this is all done by the [Clang](https://clang.llvm.org/) compiler frontend.
|
||||
* for Python the AST can be built by [parso](https://github.com/davidhalter/parso) while the references can be solved by [Jedi](https://github.com/davidhalter/jedi).
|
||||
|
||||
## Getting Started
|
||||
Ok, let's assume that you found some awesome frameworks that help you build your Sourcetrail Language Package. So what's next?
|
||||
|
||||
1. Start off by writing a small executable piece of code that reads in some input code and generates the AST. For the scope of this guide, let's assume that the following piece of Python code would be your snippet.
|
||||
|
||||
<!-- language: python -->
|
||||
class Foo:
|
||||
def bar():
|
||||
return 0
|
||||
|
||||
f = Foo()
|
||||
f.bar()
|
||||
|
||||
2. Implement an AST visitor that visits each node of the generated AST and prints that node's type. This functionality will come in handy for debugging your code later on. For our piece of sample code, the AST may look like this:
|
||||
|
||||
<!-- language: language-none -->
|
||||
file_input
|
||||
|-classdef [Foo]
|
||||
| `-funcdef [bar()]
|
||||
| `-return
|
||||
| `-number [0]
|
||||
|-assignment
|
||||
| |-name [f]
|
||||
| `-call
|
||||
| `-name [Foo()]
|
||||
|-call
|
||||
| `-name [bar()]
|
||||
| `-qualifier [f]
|
||||
`-endmarker
|
||||
3. Make the [SourcetrailDB interface](https://github.com/CoatiSoftware/SourcetrailDB#sourcetraildb-api) accessible from your code base. You can either use [existing bindings](https://github.com/CoatiSoftware/SourcetrailDB#supported-language-bindings) for your desired language or open an issue at the [SourcetrailDB issues page](https://github.com/CoatiSoftware/SourcetrailDB/issues). If your language package has made it to this stage, the SourcetrailDB team will be happy to support your project!
|
||||
4. Use SourcetrailDB from within your code base by opening a `.srctrldb` file before traversing your AST and closing it again after the AST visitor is done.
|
||||
5. Your AST should already have information available on where certain symbols are defined (e.g. `classdef [Foo]` and `funcdef [bar()]`). Try to extend your AST visitor to store this information to the Sourcetrail Database (e.g. whenever you visit a class or function declaration, try to create a node with the symbol's name (e.g. `Foo` and `Foo.bar`) in the Sourcetrail database).
|
||||
6. Setup an automated test suite that runs test cases for indexing code snippets with syntax you already covered in your language package. This way you can make sure that you don`t break things as you move forward.
|
||||
7. Extend your AST visitor to store additional information for the symbols that you already record (e.g. symbol kind, definition kind, source location).
|
||||
8. Record references between your symbols. Now, this is the tricky part. Within your AST you may encounter a node that describe references to other nodes (e.g. `call`). Use your language processing framework to resolve those references. For our example this language processing framework would need to find out that
|
||||
* `bar()` is called on the object in variable `f` and
|
||||
* `f` contains an instance of the class `Foo` so
|
||||
* `f.bar()` actually describes a call to `Foo.bar()`.
|
||||
9. If you have made it this far: Congratulations! You already have a solid Sourcetrail language package up and running! It is time to get your language package linked in the [SourcetrailDB Readme](https://github.com/CoatiSoftware/SourcetrailDB#projects-using-sourcetraildb). Just open an issue or create a pull request.
|
||||
10. Now it's just about extending the package to record more and more stuff and cover the remaining edge cases. Once the package is mature, it may be integrated and shipped with the official Sourcetrail releases, if you agree and if your licensing terms allow.
|
||||
@@ -13,8 +13,11 @@ Linux and macOS: [ database files. You can use the SourcetrailDB project to write an indexer for an arbitrary programming language (or other kind of data, e.g. see [poetry indexer example](examples/cpp_poetry_indexer)) and export a Sourcetrail database file that can be viewed and navigated within Sourcetrail.
|
||||
|
||||

|
||||
|
||||
|
||||
## Projects Using SourcetrailDB
|
||||
The following list of projects already use SourcetrailDB API to extend the language support of Sourcetrail. If you plan on starting a language package on your own, take a look at our [Language Extension Guide](LANGUAGE_EXTENSION_GUIDE.md).
|
||||
* [SourcetrailPythonIndexer](https://github.com/CoatiSoftware/SourcetrailPythonIndexer)
|
||||
|
||||
|
||||
@@ -43,6 +46,8 @@ Take a look at [Appveyor (for Windows)](appveyor.yml) or [Travis (for Linux and
|
||||
|
||||
### SourcetrailDB Core
|
||||
|
||||
Before building the core project, please make sure that you also have checked out the tags of this repository (they are relevant for deriving version number information during the build).
|
||||
|
||||
Requirements:
|
||||
* [CMake](https://cmake.org/) >= 2.6
|
||||
* C++-Compiler with C++11 support
|
||||
|
||||
+5
-4
@@ -69,9 +69,10 @@ before_build:
|
||||
- cd build
|
||||
- cmake -G "%CMAKE_GENERATOR%" ../ -DBUILD_BINDINGS_PYTHON=ON -DPYTHON_LIBRARY="%PYTHON_PATH%/libs/python%PYTHON_VERSION%.lib"
|
||||
- cd ../
|
||||
- ps: $env:CORE_VERSION = Get-Content -Path ./build/version.txt
|
||||
- ps: $env:CORE_VERSION = Get-Content -Path ./version.txt
|
||||
- ps: $env:UNDERSCORED_CORE_VERSION = $env:CORE_VERSION.Replace(".", "_")
|
||||
- ps: echo "Core version is $env:CORE_VERSION"
|
||||
# TODO: convert the core version into dotted format and update appveyor version here
|
||||
# TODO: use the core version to update appveyor version here
|
||||
# - ps: $env:BUILD_VERSION = "0.0.1." + $env:APPVEYOR_BUILD_NUMBER
|
||||
# - ps: echo update build version to $env:BUILD_VERSION
|
||||
# - ps: Update-AppveyorBuild -Version $env:BUILD_VERSION
|
||||
@@ -84,8 +85,8 @@ build_script:
|
||||
|
||||
|
||||
after_build:
|
||||
- ps: $env:CORE_PACKAGE_NAME = 'sourcetraildb_core_' + $env:CORE_VERSION + '-windows-' + $env:MBITS + 'bit-msvc' + $env:MSVC_VERSION
|
||||
- ps: $env:PYTHON_PACKAGE_NAME = 'sourcetrailbd_python' + $env:PYTHON_VERSION + '_' + $env:CORE_VERSION + '-windows-' + $env:MBITS + 'bit'
|
||||
- ps: $env:CORE_PACKAGE_NAME = 'sourcetraildb_core_' + $env:UNDERSCORED_CORE_VERSION + '-windows-' + $env:MBITS + 'bit-msvc' + $env:MSVC_VERSION
|
||||
- ps: $env:PYTHON_PACKAGE_NAME = 'sourcetrailbd_python' + $env:PYTHON_VERSION + '_' + $env:UNDERSCORED_CORE_VERSION + '-windows-' + $env:MBITS + 'bit'
|
||||
- ps: echo $env:CORE_PACKAGE_NAME
|
||||
- ps: echo $env:PYTHON_PACKAGE_NAME
|
||||
- mkdir artifacts_core
|
||||
|
||||
@@ -16,6 +16,7 @@ set(LIB_SRC_FILES
|
||||
src/DatabaseStorage.cpp
|
||||
src/DefinitionKind.cpp
|
||||
src/EdgeKind.cpp
|
||||
src/ElementComponentKind.cpp
|
||||
src/LocationKind.cpp
|
||||
src/NameHierarchy.cpp
|
||||
src/NodeKind.cpp
|
||||
@@ -32,6 +33,7 @@ set(LIB_HDR_FILES
|
||||
include/DatabaseStorage.h
|
||||
include/DefinitionKind.h
|
||||
include/EdgeKind.h
|
||||
include/ElementComponentKind.h
|
||||
include/LocationKind.h
|
||||
include/NameHierarchy.h
|
||||
include/NodeKind.h
|
||||
@@ -40,6 +42,7 @@ set(LIB_HDR_FILES
|
||||
include/SourcetrailDBWriter.h
|
||||
include/SourcetrailException.h
|
||||
include/StorageEdge.h
|
||||
include/StorageElementComponent.h
|
||||
include/StorageError.h
|
||||
include/StorageFile.h
|
||||
include/StorageLocalSymbol.h
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "CppSQLite3.h"
|
||||
|
||||
#include "StorageEdge.h"
|
||||
#include "StorageElementComponent.h"
|
||||
#include "StorageError.h"
|
||||
#include "StorageFile.h"
|
||||
#include "StorageLocalSymbol.h"
|
||||
@@ -61,6 +62,7 @@ namespace sourcetrail
|
||||
void rollbackTransaction();
|
||||
void optimizeDatabaseMemory();
|
||||
|
||||
int addElementComponent(const StorageElementComponentData& storageElementComponentData);
|
||||
int addNode(const StorageNodeData& storageNodeData);
|
||||
void addSymbol(const StorageSymbol& storageSymbol);
|
||||
void addFile(const StorageFile& storageFile);
|
||||
@@ -102,6 +104,7 @@ namespace sourcetrail
|
||||
mutable CppSQLite3DB m_database;
|
||||
|
||||
CppSQLite3Statement m_insertElementStatement;
|
||||
CppSQLite3Statement m_insertElementComponentStatement;
|
||||
CppSQLite3Statement m_findNodeStatement;
|
||||
CppSQLite3Statement m_insertNodeStatement;
|
||||
CppSQLite3Statement m_setNodeTypeStmt;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2018 Coati Software KG
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SOURCETRAIL_ELEMENT_COMPONENT_KIND_H
|
||||
#define SOURCETRAIL_ELEMENT_COMPONENT_KIND_H
|
||||
|
||||
namespace sourcetrail
|
||||
{
|
||||
/**
|
||||
* Enum providing all possible values for kinds of node and edge components that can be stored to the Sourcetrail database.
|
||||
*/
|
||||
enum class ElementComponentKind : int
|
||||
{
|
||||
IS_AMBIGUOUS = 1 << 0
|
||||
};
|
||||
|
||||
int elementComponentKindToInt(ElementComponentKind kind);
|
||||
ElementComponentKind intToElementComponentKind(int i);
|
||||
}
|
||||
|
||||
#endif // SOURCETRAIL_ELEMENT_COMPONENT_KIND_H
|
||||
@@ -29,10 +29,11 @@ namespace sourcetrail
|
||||
QUALIFIER = 2,
|
||||
LOCAL_SYMBOL = 3,
|
||||
SIGNATURE = 4,
|
||||
COMMENT = 5,
|
||||
ATOMIC_RANGE = 5,
|
||||
INDEXER_ERROR = 6,
|
||||
FULLTEXT_SEARCH = 7,
|
||||
SCREEN_SEARCH = 8
|
||||
SCREEN_SEARCH = 8,
|
||||
UNSOLVED = 9
|
||||
};
|
||||
|
||||
int locationKindToInt(LocationKind kind);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "DefinitionKind.h"
|
||||
#include "EdgeKind.h"
|
||||
#include "ElementComponentKind.h"
|
||||
#include "LocationKind.h"
|
||||
#include "NameHierarchy.h"
|
||||
#include "ReferenceKind.h"
|
||||
@@ -349,6 +350,62 @@ namespace sourcetrail
|
||||
*/
|
||||
bool recordReferenceLocation(int referenceId, const SourceRange& location);
|
||||
|
||||
/**
|
||||
* Marks a reference that is stored in the database as "ambiguous"
|
||||
*
|
||||
* This method allows to additional information for a reference to the database. Sourcetrail will
|
||||
* display an "ambiguous" reference with a special style to emphasize that the existance of the
|
||||
* reference is questionable. This method is intended to be called in situations when an indexed
|
||||
* token may have meanings, all of which shall be recorded.
|
||||
*
|
||||
* param: referenceId - the id of the reference that shall be marked as ambiguous.
|
||||
*
|
||||
* return: true if successful. false on failure. getLastError() provides the error message.
|
||||
*/
|
||||
bool recordReferenceIsAmbiuous(int referenceId);
|
||||
|
||||
/**
|
||||
* Stores a location between a specific context and an "unsolved" symbol to the database
|
||||
*
|
||||
* This method allows to store all available information to the database in the case that a symbol
|
||||
* is referenced in a certain context but the referenced symbol could not be resolved to a concrete
|
||||
* name. For each reference recorded by this method, Sourcetrail's graph view will display an edge
|
||||
* that originates at the recorded context symbol and points to a node called "unsolved symbol".
|
||||
* Furthermore Sourcetrail's code view will use a different highlight when the provided source range
|
||||
* gets hovered.
|
||||
*
|
||||
* param: contextSymbolId - the id of the source of the recorded reference edge
|
||||
* param: referenceKind - kind of the recorded reference edge
|
||||
* param: location - the SourceRange that shall be recorded as location for the respective
|
||||
* reference.
|
||||
*
|
||||
* return: referenceId - integer id of the stored reference. 0 on failure. getLastError()
|
||||
* provides the error message.
|
||||
*
|
||||
* see: SourceRange
|
||||
*/
|
||||
int recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, const SourceRange& location);
|
||||
|
||||
/**
|
||||
* Stores a location for the usage of a symbol's name as qualifier to the database
|
||||
*
|
||||
* This method allows to store a location where a specific symbol is used as a qualifier to the
|
||||
* database. Calling this method with the same referencedSymbolId multiple times adds multiple locations
|
||||
* for the respective reference. The stored location will be clickable but not displayable: When the
|
||||
* reference location is clicked Sourcetrail will activate the symbol referenced by the respective
|
||||
* reference. When the symbol with the specified id is activated, this location will NOT be displayed and
|
||||
* highlighted by Sourcetrail.
|
||||
*
|
||||
* param: referencedSymbolId - the id of the symbol that is used as qualifier at the current location.
|
||||
* param: location - the SourceRange that shall be recorded as location for the symbol's occurrence as
|
||||
* qualifier
|
||||
*
|
||||
* return: true if successful. false on failure. getLastError() provides the error message.
|
||||
*
|
||||
* see: SourceRange
|
||||
*/
|
||||
bool recordQualifierLocation(int referencedSymbolId, const SourceRange& location);
|
||||
|
||||
/**
|
||||
* Stores a file to the database
|
||||
*
|
||||
@@ -411,18 +468,21 @@ namespace sourcetrail
|
||||
bool recordLocalSymbolLocation(int localSymbolId, const SourceRange& location);
|
||||
|
||||
/**
|
||||
* Stores a comment location to the database
|
||||
* Stores an atomic SourceRange to the database
|
||||
*
|
||||
* This method allows to store a comment location to the database. These comment locations will
|
||||
* be used by Sourcetrail to prevent the code view from displaying comments imcomplete.
|
||||
* This method allows to store an atomic SourceRange to the database. These ranges will
|
||||
* be used by Sourcetrail to prevent the code view from displaying only a part of the range. Thus,
|
||||
* if any line that lies within one of the project's atomic ranges is dispayed, the remaining
|
||||
* lines will be displayed as well. This may be useful for dealing with multi-line comments or
|
||||
* multi-line strings.
|
||||
*
|
||||
* param: location - the SourceRange of the comment to record.
|
||||
* param: sourceRange - the SourceRange to record.
|
||||
*
|
||||
* return: true if successful. false on failure. getLastError() provides the error message.
|
||||
*
|
||||
* see: SourceRange
|
||||
*/
|
||||
bool recordCommentLocation(const SourceRange& location);
|
||||
bool recordAtomicSourceRange(const SourceRange& sourceRange);
|
||||
|
||||
/**
|
||||
* Stores an indexing error to the database
|
||||
@@ -452,6 +512,7 @@ namespace sourcetrail
|
||||
int addFile(const std::string& filePath);
|
||||
int addEdge(int sourceId, int targetId, EdgeKind edgeKind);
|
||||
void addSourceLocation(int elementId, const SourceRange& location, LocationKind kind);
|
||||
void addElementComponent(int elementId, ElementComponentKind kind, const std::string& data);
|
||||
|
||||
std::string m_projectFilePath;
|
||||
std::string m_databaseFilePath;
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2018 Coati Software KG
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SOURCETRAIL_STORAGE_ELEMENT_COMPONENT_H
|
||||
#define SOURCETRAIL_STORAGE_ELEMENT_COMPONENT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace sourcetrail
|
||||
{
|
||||
struct StorageElementComponentData
|
||||
{
|
||||
StorageElementComponentData()
|
||||
: elementId(0)
|
||||
, componentKind(0)
|
||||
, data("")
|
||||
{}
|
||||
|
||||
StorageElementComponentData(int elementId, int componentKind, std::string data)
|
||||
: elementId(elementId)
|
||||
, componentKind(componentKind)
|
||||
, data(std::move(data))
|
||||
{}
|
||||
|
||||
int elementId;
|
||||
int componentKind;
|
||||
std::string data;
|
||||
};
|
||||
|
||||
struct StorageElementComponent : public StorageElementComponentData
|
||||
{
|
||||
StorageElementComponent()
|
||||
: StorageElementComponentData()
|
||||
, id(0)
|
||||
{}
|
||||
|
||||
StorageElementComponent(int id, const StorageElementComponentData& data)
|
||||
: StorageElementComponentData(data)
|
||||
, id(id)
|
||||
{}
|
||||
|
||||
StorageElementComponent(int id, int elementId, int componentKind, std::string data)
|
||||
: StorageElementComponentData(elementId, componentKind, data)
|
||||
, id(id)
|
||||
{}
|
||||
|
||||
int id;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SOURCETRAIL_STORAGE_ELEMENT_COMPONENT_H
|
||||
@@ -151,6 +151,17 @@ namespace sourcetrail
|
||||
executeStatement("VACUUM;");
|
||||
}
|
||||
|
||||
int DatabaseStorage::addElementComponent(const StorageElementComponentData& storageElementComponentData)
|
||||
{
|
||||
m_insertElementComponentStatement.bind(1, storageElementComponentData.elementId);
|
||||
m_insertElementComponentStatement.bind(2, storageElementComponentData.componentKind);
|
||||
m_insertElementComponentStatement.bind(3, storageElementComponentData.data.c_str());
|
||||
executeStatement(m_insertElementComponentStatement);
|
||||
int id = m_database.lastRowId();
|
||||
m_insertElementComponentStatement.reset();
|
||||
return id;
|
||||
}
|
||||
|
||||
int DatabaseStorage::addNode(const StorageNodeData& storageNodeData)
|
||||
{
|
||||
int id = 0;
|
||||
@@ -393,6 +404,17 @@ namespace sourcetrail
|
||||
");"
|
||||
);
|
||||
|
||||
executeStatement(
|
||||
"CREATE TABLE IF NOT EXISTS element_component("
|
||||
" id INTEGER, "
|
||||
" element_id INTEGER, "
|
||||
" type INTEGER, "
|
||||
" data TEXT, "
|
||||
" PRIMARY KEY(id), "
|
||||
" FOREIGN KEY(element_id) REFERENCES element(id) ON DELETE CASCADE"
|
||||
");"
|
||||
);
|
||||
|
||||
executeStatement(
|
||||
"CREATE TABLE IF NOT EXISTS edge("
|
||||
" id INTEGER NOT NULL, "
|
||||
@@ -518,6 +540,7 @@ namespace sourcetrail
|
||||
"symbol",
|
||||
"node",
|
||||
"edge",
|
||||
"element_component"
|
||||
"element"
|
||||
};
|
||||
|
||||
@@ -557,6 +580,10 @@ namespace sourcetrail
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
|
||||
m_insertElementComponentStatement = compileStatement(
|
||||
"INSERT INTO element_component(id, element_id, type, data) VALUES(NULL, ?, ?, ?);"
|
||||
);
|
||||
|
||||
m_findNodeStatement = compileStatement(
|
||||
"SELECT id FROM node WHERE serialized_name == ? LIMIT 1;"
|
||||
);
|
||||
@@ -648,6 +675,7 @@ namespace sourcetrail
|
||||
void DatabaseStorage::clearPrecompiledStatements()
|
||||
{
|
||||
m_insertElementStatement.finalize();
|
||||
m_insertElementComponentStatement.finalize();
|
||||
m_findNodeStatement.finalize();
|
||||
m_insertNodeStatement.finalize();
|
||||
m_setNodeTypeStmt.finalize();
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2018 Coati Software KG
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ElementComponentKind.h"
|
||||
|
||||
#include "SourcetrailException.h"
|
||||
|
||||
namespace sourcetrail
|
||||
{
|
||||
int elementComponentKindToInt(ElementComponentKind kind)
|
||||
{
|
||||
return static_cast<int>(kind);
|
||||
}
|
||||
|
||||
ElementComponentKind intToElementComponentKind(int i)
|
||||
{
|
||||
const ElementComponentKind kinds[] = {
|
||||
ElementComponentKind::IS_AMBIGUOUS
|
||||
};
|
||||
|
||||
for (ElementComponentKind kind : kinds)
|
||||
{
|
||||
if (i == elementComponentKindToInt(kind))
|
||||
{
|
||||
return kind;
|
||||
}
|
||||
}
|
||||
|
||||
throw SourcetrailException("Unable to convert integer \"" + std::to_string(i) + "\" to element component kind.");
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,11 @@ namespace sourcetrail
|
||||
LocationKind::QUALIFIER,
|
||||
LocationKind::LOCAL_SYMBOL,
|
||||
LocationKind::SIGNATURE,
|
||||
LocationKind::COMMENT,
|
||||
LocationKind::ATOMIC_RANGE,
|
||||
LocationKind::INDEXER_ERROR,
|
||||
LocationKind::FULLTEXT_SEARCH,
|
||||
LocationKind::SCREEN_SEARCH
|
||||
LocationKind::SCREEN_SEARCH,
|
||||
LocationKind::UNSOLVED
|
||||
};
|
||||
|
||||
for (LocationKind kind : kinds)
|
||||
|
||||
@@ -428,7 +428,7 @@ namespace sourcetrail
|
||||
if (!m_storage)
|
||||
{
|
||||
m_lastError = "Unable to record reference, because no database is currently open.";
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -446,7 +446,7 @@ namespace sourcetrail
|
||||
{
|
||||
if (!m_storage)
|
||||
{
|
||||
m_lastError = "Unable to record symbol signature location, because no database is currently open.";
|
||||
m_lastError = "Unable to record symbol reference location, because no database is currently open.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -462,6 +462,72 @@ namespace sourcetrail
|
||||
}
|
||||
}
|
||||
|
||||
bool SourcetrailDBWriter::recordReferenceIsAmbiuous(int referenceId)
|
||||
{
|
||||
if (!m_storage)
|
||||
{
|
||||
m_lastError = "Unable to record ambiguity of reference, because no database is currently open.";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
addElementComponent(referenceId, ElementComponentKind::IS_AMBIGUOUS, "");
|
||||
return false;
|
||||
}
|
||||
catch (const SourcetrailException e)
|
||||
{
|
||||
m_lastError = e.getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int SourcetrailDBWriter::recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, const SourceRange& location)
|
||||
{
|
||||
if (!m_storage)
|
||||
{
|
||||
m_lastError = "Unable to record symbol reference, because no database is currently open.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NameHierarchy unsolvedSymbolName;
|
||||
NameElement unsolvedSymbolNameElement;
|
||||
unsolvedSymbolNameElement.name = "unsolved symbol";
|
||||
unsolvedSymbolName.nameElements.push_back(unsolvedSymbolNameElement);
|
||||
int unsolvedSymbolId = addNodeHierarchy(unsolvedSymbolName);
|
||||
int referenceId = addEdge(contextSymbolId, unsolvedSymbolId, referenceKindToEdgeKind(referenceKind));
|
||||
addSourceLocation(referenceId, location, LocationKind::UNSOLVED);
|
||||
return referenceId;
|
||||
}
|
||||
catch (const SourcetrailException e)
|
||||
{
|
||||
m_lastError = e.getMessage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool SourcetrailDBWriter::recordQualifierLocation(int referencedSymbolId, const SourceRange& location)
|
||||
{
|
||||
if (!m_storage)
|
||||
{
|
||||
m_lastError = "Unable to record symbol qualifier location, because no database is currently open.";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
addSourceLocation(referencedSymbolId, location, LocationKind::QUALIFIER);
|
||||
return true;
|
||||
}
|
||||
catch (const SourcetrailException e)
|
||||
{
|
||||
m_lastError = e.getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int SourcetrailDBWriter::recordFile(const std::string& filePath)
|
||||
{
|
||||
if (!m_storage)
|
||||
@@ -541,23 +607,23 @@ namespace sourcetrail
|
||||
}
|
||||
}
|
||||
|
||||
bool SourcetrailDBWriter::recordCommentLocation(const SourceRange& location)
|
||||
bool SourcetrailDBWriter::recordAtomicSourceRange(const SourceRange& sourceRange)
|
||||
{
|
||||
if (!m_storage)
|
||||
{
|
||||
m_lastError = "Unable to record comment location, because no database is currently open.";
|
||||
m_lastError = "Unable to record atomic source range, because no database is currently open.";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
const int sourceLocationId = m_storage->addSourceLocation(StorageSourceLocationData(
|
||||
location.fileId,
|
||||
location.startLine,
|
||||
location.startColumn,
|
||||
location.endLine,
|
||||
location.endColumn,
|
||||
locationKindToInt(LocationKind::COMMENT)
|
||||
sourceRange.fileId,
|
||||
sourceRange.startLine,
|
||||
sourceRange.startColumn,
|
||||
sourceRange.endLine,
|
||||
sourceRange.endColumn,
|
||||
locationKindToInt(LocationKind::ATOMIC_RANGE)
|
||||
));
|
||||
|
||||
return true;
|
||||
@@ -765,4 +831,13 @@ namespace sourcetrail
|
||||
sourceLocationId
|
||||
));
|
||||
}
|
||||
|
||||
void SourcetrailDBWriter::addElementComponent(int elementId, ElementComponentKind kind, const std::string& data)
|
||||
{
|
||||
const int sourceLocationId = m_storage->addElementComponent(StorageElementComponentData(
|
||||
elementId,
|
||||
elementComponentKindToInt(kind),
|
||||
data
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
+55
-4
@@ -276,6 +276,57 @@ namespace sourcetrail
|
||||
REQUIRE(writer.getLastError() == "");
|
||||
}
|
||||
|
||||
TEST_CASE("Testing SourcetrailDBWriter records qualifier locations")
|
||||
{
|
||||
const std::string databasePath = "testing.db";
|
||||
|
||||
std::shared_ptr<DatabaseStorage> storage = DatabaseStorage::openDatabase(databasePath);
|
||||
|
||||
SourcetrailDBWriter writer;
|
||||
REQUIRE(writer.getLastError() == "");
|
||||
|
||||
writer.open(databasePath);
|
||||
REQUIRE(writer.getLastError() == "");
|
||||
|
||||
writer.clear();
|
||||
REQUIRE(writer.getLastError() == "");
|
||||
|
||||
const NameHierarchy nameSymbol1({ "." ,{ { "", "Foo", "" } } });
|
||||
const int idSymbol1 = writer.recordSymbol(nameSymbol1);
|
||||
REQUIRE(idSymbol1 != 0);
|
||||
REQUIRE(writer.getLastError() == "");
|
||||
|
||||
const std::string filePath = "path/to/non_existing_file.cpp";
|
||||
const int fileId = writer.recordFile(filePath);
|
||||
const int startLine = 1;
|
||||
const int startCol = 2;
|
||||
const int endLine = 3;
|
||||
const int endCol = 4;
|
||||
|
||||
const bool success = writer.recordQualifierLocation(idSymbol1, { fileId, startLine, startCol, endLine, endCol });
|
||||
REQUIRE(success);
|
||||
REQUIRE(writer.getLastError() == "");
|
||||
|
||||
SECTION("database contains qualifier location after recording qualifier location")
|
||||
{
|
||||
const std::vector<StorageSourceLocation> sourceLocations = storage->getAll<StorageSourceLocation>();
|
||||
REQUIRE(sourceLocations.size() == 1);
|
||||
REQUIRE(sourceLocations.front().locationKind == locationKindToInt(LocationKind::QUALIFIER));
|
||||
REQUIRE(sourceLocations.front().startLineNumber == startLine);
|
||||
REQUIRE(sourceLocations.front().startColumnNumber == startCol);
|
||||
REQUIRE(sourceLocations.front().endLineNumber == endLine);
|
||||
REQUIRE(sourceLocations.front().endColumnNumber == endCol);
|
||||
|
||||
const std::vector<StorageFile> files = storage->getAll<StorageFile>();
|
||||
REQUIRE(files.size() == 1);
|
||||
REQUIRE(files.front().filePath == filePath);
|
||||
REQUIRE(sourceLocations.front().fileNodeId == files.front().id);
|
||||
}
|
||||
|
||||
writer.close();
|
||||
REQUIRE(writer.getLastError() == "");
|
||||
}
|
||||
|
||||
TEST_CASE("Testing SourcetrailDBWriter records file")
|
||||
{
|
||||
const std::string databasePath = "testing.db";
|
||||
@@ -435,7 +486,7 @@ namespace sourcetrail
|
||||
const int endLine = 3;
|
||||
const int endCol = 4;
|
||||
|
||||
const bool success1 = writer.recordCommentLocation(
|
||||
const bool success1 = writer.recordAtomicSourceRange(
|
||||
{ fileId, startLine, startCol, endLine, endCol }
|
||||
);
|
||||
REQUIRE(success1);
|
||||
@@ -445,7 +496,7 @@ namespace sourcetrail
|
||||
{
|
||||
const std::vector<StorageSourceLocation> sourceLocations = storage->getAll<StorageSourceLocation>();
|
||||
REQUIRE(sourceLocations.size() == 1);
|
||||
REQUIRE(sourceLocations.front().locationKind == locationKindToInt(LocationKind::COMMENT));
|
||||
REQUIRE(sourceLocations.front().locationKind == locationKindToInt(LocationKind::ATOMIC_RANGE));
|
||||
REQUIRE(sourceLocations.front().startLineNumber == startLine);
|
||||
REQUIRE(sourceLocations.front().startColumnNumber == startCol);
|
||||
REQUIRE(sourceLocations.front().endLineNumber == endLine);
|
||||
@@ -457,9 +508,9 @@ namespace sourcetrail
|
||||
REQUIRE(sourceLocations.front().fileNodeId == files.front().id);
|
||||
}
|
||||
|
||||
SECTION("writer does not record comment location twice")
|
||||
SECTION("writer does not record atomic source range twice")
|
||||
{
|
||||
const bool success2 = writer.recordCommentLocation(
|
||||
const bool success2 = writer.recordAtomicSourceRange(
|
||||
{ fileId, startLine, startCol, endLine, endCol }
|
||||
);
|
||||
REQUIRE(success2);
|
||||
|
||||
@@ -4,6 +4,17 @@
|
||||
|
||||
#include "SourcetrailDBWriter.h"
|
||||
|
||||
void findAndReplaceAll(std::string &data, const std::string &toSearch, const std::string &replaceStr)
|
||||
{
|
||||
size_t pos = data.find(toSearch);
|
||||
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
data.replace(pos, toSearch.size(), replaceStr);
|
||||
pos = data.find(toSearch, pos + replaceStr.size());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
sourcetrail::SourcetrailDBWriter dbWriter;
|
||||
@@ -21,6 +32,7 @@ int main(int argc, const char *argv[])
|
||||
|
||||
std::string dbPath = argv[1];
|
||||
std::string sourcePath = argv[2];
|
||||
findAndReplaceAll(sourcePath, "\\", "/");
|
||||
|
||||
int dbVersion = 0;
|
||||
if (argc == 4)
|
||||
@@ -44,6 +56,13 @@ int main(int argc, const char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Clearing Database... " << std::endl;
|
||||
if (!dbWriter.clear())
|
||||
{
|
||||
std::cerr << "error: " << dbWriter.getLastError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Starting Indexing..." << std::endl;
|
||||
|
||||
// start recording with faster speed
|
||||
@@ -58,8 +77,8 @@ int main(int argc, const char *argv[])
|
||||
dbWriter.recordFileLanguage(fileId, "cpp"); // record file language for syntax highlighting
|
||||
|
||||
|
||||
// record comment
|
||||
dbWriter.recordCommentLocation({ fileId, 2, 1, 6, 3 });
|
||||
// record atomic source range for multi line comment
|
||||
dbWriter.recordAtomicSourceRange({ fileId, 2, 1, 6, 3 });
|
||||
|
||||
|
||||
// record namespace "api"
|
||||
@@ -83,7 +102,7 @@ int main(int argc, const char *argv[])
|
||||
|
||||
// record inheritance reference to "BaseType"
|
||||
int baseId = dbWriter.recordSymbol( { "::", { { "", "BaseType", "" } } } );
|
||||
int inheritanceId = dbWriter.recordReference(baseId, classId, sourcetrail::ReferenceKind::INHERITANCE);
|
||||
int inheritanceId = dbWriter.recordReference(classId, baseId, sourcetrail::ReferenceKind::INHERITANCE);
|
||||
dbWriter.recordReferenceLocation(inheritanceId, { fileId, 12, 14, 12, 21 });
|
||||
|
||||
|
||||
@@ -98,7 +117,7 @@ int main(int argc, const char *argv[])
|
||||
dbWriter.recordSymbolSignatureLocation(methodId, { fileId, 15, 5, 15, 45 }); // used in tooltip
|
||||
|
||||
|
||||
// record parameter type "bool"
|
||||
// record usage of parameter type "bool"
|
||||
int typeId = dbWriter.recordSymbol({ "::", { { "", "bool", "" } } });
|
||||
int typeuseId = dbWriter.recordReference(methodId, typeId, sourcetrail::ReferenceKind::TYPE_USAGE);
|
||||
dbWriter.recordReferenceLocation(typeuseId, { fileId, 15, 20, 15, 23 });
|
||||
@@ -110,11 +129,16 @@ int main(int argc, const char *argv[])
|
||||
dbWriter.recordLocalSymbolLocation(localId, { fileId, 17, 13, 17, 26 });
|
||||
|
||||
|
||||
// record source range of "Client" as qualifier location
|
||||
int qualifierId = dbWriter.recordSymbol({ "::",{ { "", "Client", "" } } });
|
||||
dbWriter.recordQualifierLocation(qualifierId, { fileId, 19, 13, 19, 18 });
|
||||
|
||||
|
||||
// record function call reference to "send_signal()"
|
||||
int funcId = dbWriter.recordSymbol({ "::", { { "", "Client", "" }, { "", "send_signal", "()" } } });
|
||||
dbWriter.recordSymbolKind(funcId, sourcetrail::SymbolKind::FUNCTION);
|
||||
int callId = dbWriter.recordReference(methodId, funcId, sourcetrail::ReferenceKind::CALL);
|
||||
dbWriter.recordReferenceLocation(callId, { fileId, 19, 13, 19, 33 });
|
||||
dbWriter.recordReferenceLocation(callId, { fileId, 19, 21, 19, 31 });
|
||||
|
||||
|
||||
// record error
|
||||
|
||||
@@ -13,7 +13,7 @@ def main():
|
||||
|
||||
args = parser.parse_args()
|
||||
databaseFilePath = args.database_file_path
|
||||
sourceFilePath = args.source_file_path
|
||||
sourceFilePath = args.source_file_path.replace("\\", "/")
|
||||
dbVersion = args.database_version
|
||||
|
||||
print("SourcetrailDB Python API Example")
|
||||
@@ -28,10 +28,8 @@ def main():
|
||||
print("ERROR: " + srctrl.getLastError())
|
||||
return 1
|
||||
|
||||
if srctrl.isEmpty():
|
||||
print("Loaded database is empty.")
|
||||
else:
|
||||
print("Loaded database contains data.")
|
||||
print("Clearing loaded database now...")
|
||||
srctrl.clear()
|
||||
|
||||
print("start indexing")
|
||||
srctrl.beginTransaction()
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 669 KiB |
@@ -51,6 +51,8 @@ enum ReferenceKind
|
||||
REFERENCE_ANNOTATION_USAGE
|
||||
};
|
||||
|
||||
std::string getVersionString();
|
||||
|
||||
int getSupportedDatabaseVersion();
|
||||
|
||||
std::string getLastError();
|
||||
@@ -93,6 +95,12 @@ int recordReference(int contextSymbolId, int referencedSymbolId, ReferenceKind r
|
||||
|
||||
bool recordReferenceLocation(int referenceId, int fileId, int startLine, int startColumn, int endLine, int endColumn);
|
||||
|
||||
bool recordReferenceIsAmbiuous(int referenceId);
|
||||
|
||||
int recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, int fileId, int startLine, int startColumn, int endLine, int endColumn);
|
||||
|
||||
bool recordQualifierLocation(int referencedSymbolId, int fileId, int startLine, int startColumn, int endLine, int endColumn);
|
||||
|
||||
int recordFile(std::string filePath);
|
||||
|
||||
bool recordFileLanguage(int fileId, std::string languageIdentifier);
|
||||
@@ -101,7 +109,7 @@ int recordLocalSymbol(std::string name);
|
||||
|
||||
bool recordLocalSymbolLocation(int localSymbolId, int fileId, int startLine, int startColumn, int endLine, int endColumn);
|
||||
|
||||
bool recordCommentLocation(int fileId, int startLine, int startColumn, int endLine, int endColumn);
|
||||
bool recordAtomicSourceRange(int fileId, int startLine, int startColumn, int endLine, int endColumn);
|
||||
|
||||
bool recordError(std::string message, bool fatal, int fileId, int startLine, int startColumn, int endLine, int endColumn);
|
||||
|
||||
|
||||
@@ -108,6 +108,11 @@ namespace
|
||||
|
||||
sourcetrail::SourcetrailDBWriter dbWriter;
|
||||
|
||||
std::string getVersionString()
|
||||
{
|
||||
return dbWriter.getVersionString();
|
||||
}
|
||||
|
||||
int getSupportedDatabaseVersion()
|
||||
{
|
||||
return dbWriter.getSupportedDatabaseVersion();
|
||||
@@ -220,6 +225,21 @@ bool recordReferenceLocation(int referenceId, int fileId, int startLine, int sta
|
||||
return dbWriter.recordReferenceLocation(referenceId, { fileId, startLine, startColumn, endLine, endColumn });
|
||||
}
|
||||
|
||||
bool recordReferenceIsAmbiuous(int referenceId)
|
||||
{
|
||||
return dbWriter.recordReferenceIsAmbiuous(referenceId);
|
||||
}
|
||||
|
||||
int recordReferenceToUnsolvedSymhol(int contextSymbolId, ReferenceKind referenceKind, int fileId, int startLine, int startColumn, int endLine, int endColumn)
|
||||
{
|
||||
return dbWriter.recordReferenceToUnsolvedSymhol(contextSymbolId, convertReferenceKind(referenceKind), { fileId, startLine, startColumn, endLine, endColumn });
|
||||
}
|
||||
|
||||
bool recordQualifierLocation(int referencedSymbolId, int fileId, int startLine, int startColumn, int endLine, int endColumn)
|
||||
{
|
||||
return dbWriter.recordQualifierLocation(referencedSymbolId, { fileId, startLine, startColumn, endLine, endColumn });
|
||||
}
|
||||
|
||||
int recordFile(std::string filePath)
|
||||
{
|
||||
return dbWriter.recordFile(filePath);
|
||||
@@ -240,9 +260,9 @@ bool recordLocalSymbolLocation(int localSymbolId, int fileId, int startLine, int
|
||||
return dbWriter.recordLocalSymbolLocation(localSymbolId, { fileId, startLine, startColumn, endLine, endColumn });
|
||||
}
|
||||
|
||||
bool recordCommentLocation(int fileId, int startLine, int startColumn, int endLine, int endColumn)
|
||||
bool recordAtomicSourceRange(int fileId, int startLine, int startColumn, int endLine, int endColumn)
|
||||
{
|
||||
return dbWriter.recordCommentLocation({ fileId, startLine, startColumn, endLine, endColumn });
|
||||
return dbWriter.recordAtomicSourceRange({ fileId, startLine, startColumn, endLine, endColumn });
|
||||
}
|
||||
|
||||
bool recordError(std::string message, bool fatal, int fileId, int startLine, int startColumn, int endLine, int endColumn)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
v2.db24.p0
|
||||
@@ -1 +0,0 @@
|
||||
@VERSION_STRING_UNDERSCORE@
|
||||
Reference in New Issue
Block a user