logic: show real code of signatures in tooltips

* added new location type
* refactored old recording code
* record signature locations for cxx functions and java methods
* added signature locations to sample project indexer tests
* ignore signature locations in ui
* signatures in tooltip with qualified name of the function/method
* added test for finding signature location of constructor with initializer list
This commit is contained in:
mlangkabel
2018-07-20 14:00:08 +02:00
parent 605d07688b
commit c6f9d8f92c
211 changed files with 19809 additions and 19293 deletions
+3 -1
View File
@@ -17,8 +17,10 @@ LocationType intToLocationType(int value)
return LOCATION_QUALIFIER;
case LOCATION_LOCAL_SYMBOL:
return LOCATION_LOCAL_SYMBOL;
case LOCATION_SIGNATURE:
return LOCATION_SIGNATURE;
case LOCATION_ERROR:
return LOCATION_ERROR;
return LOCATION_ERROR;
case LOCATION_FULLTEXT_SEARCH:
return LOCATION_FULLTEXT_SEARCH;
case LOCATION_SCREEN_SEARCH:
+4 -3
View File
@@ -7,9 +7,10 @@ enum LocationType
LOCATION_SCOPE = 1,
LOCATION_QUALIFIER = 2,
LOCATION_LOCAL_SYMBOL = 3,
LOCATION_ERROR = 4,
LOCATION_FULLTEXT_SEARCH = 5,
LOCATION_SCREEN_SEARCH = 6
LOCATION_SIGNATURE = 4,
LOCATION_ERROR = 5,
LOCATION_FULLTEXT_SEARCH = 6,
LOCATION_SCREEN_SEARCH = 7
};
int locationTypeToInt(LocationType type);
+33
View File
@@ -91,6 +91,39 @@ bool SourceLocation::operator>(const SourceLocation& rhs) const
return getLocationId() > rhs.getLocationId();
}
bool SourceLocation::contains(const SourceLocation& other) const
{
const SourceLocation* start = getStartLocation();
const SourceLocation* otherStart = other.getStartLocation();
if (start->getLineNumber() > otherStart->getLineNumber())
{
return false;
}
if (start->getLineNumber() == otherStart->getLineNumber() &&
start->getColumnNumber() > otherStart->getColumnNumber())
{
return false;
}
const SourceLocation* end = getEndLocation();
const SourceLocation* otherEnd = other.getEndLocation();
if (end->getLineNumber() < otherEnd->getLineNumber())
{
return false;
}
if (end->getLineNumber() == otherEnd->getLineNumber() &&
end->getColumnNumber() < otherEnd->getColumnNumber())
{
return false;
}
return true;
}
SourceLocationFile* SourceLocation::getSourceLocationFile() const
{
return m_file;
+2
View File
@@ -24,6 +24,8 @@ public:
bool operator<(const SourceLocation& rhs) const;
bool operator>(const SourceLocation& rhs) const;
bool contains(const SourceLocation& other) const;
SourceLocationFile* getSourceLocationFile() const;
Id getLocationId() const;
+27
View File
@@ -70,6 +70,33 @@ std::wstring ParserClient::addLocationSuffix(
return ss.str();
}
std::wstring ParserClient::addLocationSuffix(
const std::wstring& str, const ParseLocation& location, const ParseLocation& scopeLocation, const ParseLocation& signatureLocation
) {
if (!location.isValid())
{
return addLocationSuffix(str, scopeLocation, signatureLocation);
}
if (!scopeLocation.isValid())
{
return addLocationSuffix(str, location, signatureLocation);
}
if (!signatureLocation.isValid())
{
return addLocationSuffix(str, location, scopeLocation);
}
std::wstringstream ss;
ss << str;
ss << L" <" << scopeLocation.startLineNumber << L":" << scopeLocation.startColumnNumber;
ss << L" <" << signatureLocation.startLineNumber << L":" << signatureLocation.startColumnNumber << L" ";
ss << L" <" << location.startLineNumber << L":" << location.startColumnNumber << L" ";
ss << location.endLineNumber << L":" << location.endColumnNumber << L"> ";
ss << signatureLocation.endLineNumber << L":" << signatureLocation.endColumnNumber << L"> ";
ss << scopeLocation.endLineNumber << L":" << scopeLocation.endColumnNumber << L">";
return ss.str();
}
ParserClient::ParserClient()
: m_hasFatalErrors(false)
{
+13 -2
View File
@@ -24,6 +24,12 @@ public:
static std::wstring addLocationSuffix(const std::wstring& str, const ParseLocation& location);
static std::wstring addLocationSuffix(
const std::wstring& str, const ParseLocation& location, const ParseLocation& scopeLocation);
static std::wstring addLocationSuffix(
const std::wstring& str,
const ParseLocation& location,
const ParseLocation& scopeLocation,
const ParseLocation& signatureLocation
);
ParserClient();
virtual ~ParserClient() = default;
@@ -32,16 +38,21 @@ public:
const NameHierarchy& symbolName, SymbolKind symbolKind,
AccessKind access, DefinitionKind definitionKind) = 0;
virtual Id recordSymbol(
virtual Id recordSymbolWithLocation(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location,
AccessKind access, DefinitionKind definitionKind) = 0;
virtual Id recordSymbol(
virtual Id recordSymbolWithLocationAndScope(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location, const ParseLocation& scopeLocation,
AccessKind access, DefinitionKind definitionKind) = 0;
virtual Id recordSymbolWithLocationAndScopeAndSignature(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location, const ParseLocation& scopeLocation, const ParseLocation& signatureLocation,
AccessKind access, DefinitionKind definitionKind) = 0;
virtual void recordReference(
ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName,
const ParseLocation& location) = 0;
+13 -7
View File
@@ -10,10 +10,6 @@ ParserClientImpl::ParserClientImpl()
{
}
ParserClientImpl::~ParserClientImpl()
{
}
void ParserClientImpl::setStorage(std::shared_ptr<IntermediateStorage> storage)
{
m_storage = storage;
@@ -35,7 +31,7 @@ Id ParserClientImpl::recordSymbol(
return nodeId;
}
Id ParserClientImpl::recordSymbol(
Id ParserClientImpl::recordSymbolWithLocation(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location,
AccessKind access, DefinitionKind definitionKind
@@ -46,17 +42,27 @@ Id ParserClientImpl::recordSymbol(
return nodeId;
}
Id ParserClientImpl::recordSymbol(
Id ParserClientImpl::recordSymbolWithLocationAndScope(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location, const ParseLocation& scopeLocation,
AccessKind access, DefinitionKind definitionKind
)
{
Id nodeId = recordSymbol(symbolName, symbolKind, location, access, definitionKind);
Id nodeId = recordSymbolWithLocation(symbolName, symbolKind, location, access, definitionKind);
addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE));
return nodeId;
}
Id ParserClientImpl::recordSymbolWithLocationAndScopeAndSignature(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location, const ParseLocation& scopeLocation, const ParseLocation& signatureLocation,
AccessKind access, DefinitionKind definitionKind)
{
Id nodeId = recordSymbolWithLocation(symbolName, symbolKind, location, access, definitionKind);
addSourceLocation(nodeId, signatureLocation, locationTypeToInt(LOCATION_SIGNATURE));
return nodeId;
}
void ParserClientImpl::recordReference(
ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName,
const ParseLocation& location)
+15 -11
View File
@@ -13,38 +13,42 @@ class ParserClientImpl
{
public:
ParserClientImpl();
virtual ~ParserClientImpl();
void setStorage(std::shared_ptr<IntermediateStorage> storage);
void resetStorage();
virtual Id recordSymbol(
Id recordSymbol(
const NameHierarchy& symbolName, SymbolKind symbolKind,
AccessKind access, DefinitionKind definitionKind) override;
virtual Id recordSymbol(
Id recordSymbolWithLocation(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location,
AccessKind access, DefinitionKind definitionKind) override;
virtual Id recordSymbol(
Id recordSymbolWithLocationAndScope(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location, const ParseLocation& scopeLocation,
AccessKind access, DefinitionKind definitionKind) override;
virtual void recordReference(
Id recordSymbolWithLocationAndScopeAndSignature(
const NameHierarchy& symbolName, SymbolKind symbolKind,
const ParseLocation& location, const ParseLocation& scopeLocation, const ParseLocation& signatureLocation,
AccessKind access, DefinitionKind definitionKind) override;
void recordReference(
ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName,
const ParseLocation& location) override;
virtual void recordQualifierLocation(
void recordQualifierLocation(
const NameHierarchy& qualifierName, const ParseLocation& location) override;
virtual void recordLocalSymbol(const std::wstring& name, const ParseLocation& location) override;
virtual void recordFile(const FileInfo& fileInfo, bool indexed) override;
virtual void recordComment(const ParseLocation& location) override;
void recordLocalSymbol(const std::wstring& name, const ParseLocation& location) override;
void recordFile(const FileInfo& fileInfo, bool indexed) override;
void recordComment(const ParseLocation& location) override;
private:
virtual void doRecordError(
void doRecordError(
const ParseLocation& location, const std::wstring& message, bool fatal, bool indexed, const FilePath& sourceFilePath) override;
NodeType symbolKindToNodeType(SymbolKind symbolType) const;
+122 -1
View File
@@ -1391,7 +1391,7 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getSourceLocationsF
for (const StorageSourceLocation& sourceLocation: m_sqliteIndexStorage.getAllByIds<StorageSourceLocation>(locationIds))
{
const LocationType type = intToLocationType(sourceLocation.type);
if (type == LOCATION_QUALIFIER)
if (type == LOCATION_QUALIFIER || type == LOCATION_SIGNATURE)
{
continue;
}
@@ -1967,6 +1967,127 @@ TooltipSnippet PersistentStorage::getTooltipSnippetForNode(const StorageNode& no
if (nameHierarchy.hasSignature())
{
std::shared_ptr<SourceLocationCollection> locations = m_sqliteIndexStorage.getSourceLocationsForElementIds({ node.id });
SourceLocation* sigLoc = nullptr;
locations->forEachSourceLocation(
[&sigLoc](SourceLocation* location)
{
if (!sigLoc && location->isStartLocation() && location->getType() == LOCATION_SIGNATURE)
{
sigLoc = location;
}
}
);
// if node has a signature location use that one
if (sigLoc)
{
struct Annotation
{
Id locationId = 0;
size_t startPos = 0;
size_t endPos = 0;
};
std::vector<Annotation> annotations;
std::vector<std::string> lines = getFileContent(sigLoc->getFilePath())->getLines(
sigLoc->getLineNumber(), sigLoc->getEndLocation()->getLineNumber());
std::shared_ptr<SourceLocationFile> file = getSourceLocationsForLinesInFile(
sigLoc->getFilePath(),
sigLoc->getStartLocation()->getLineNumber(),
sigLoc->getEndLocation()->getLineNumber()
);
file->forEachStartSourceLocation(
[&sigLoc, &annotations, &lines](SourceLocation* loc)
{
if ((loc->getType() == LOCATION_TOKEN || loc->getType() == LOCATION_QUALIFIER) &&
sigLoc->contains(*loc))
{
Annotation annotation;
annotation.locationId = loc->getLocationId();
for (size_t i = 0; i < loc->getLineNumber() - sigLoc->getLineNumber(); i++)
{
annotation.startPos += lines[i].size();
}
annotation.startPos += loc->getColumnNumber() - sigLoc->getColumnNumber();
for (size_t i = 0; i < loc->getEndLocation()->getLineNumber() - sigLoc->getLineNumber(); i++)
{
annotation.endPos += lines[i].size();
}
annotation.endPos += loc->getEndLocation()->getColumnNumber() - sigLoc->getColumnNumber();
annotations.push_back(annotation);
}
}
);
// remove characters after signature end
lines[lines.size()-1] = lines[lines.size()-1].substr(0, sigLoc->getEndLocation()->getColumnNumber());
// remove characters before signature start
lines[0] = lines[0].substr(sigLoc->getColumnNumber() - 1);
std::wstring code = utility::decodeFromUtf8(utility::join(lines, ""));
// store texts of annotations
std::vector<std::pair<Id, std::wstring>> annotatedTexts;
size_t offset = 0;
for (const Annotation& annotation : annotations)
{
std::wstring text = code.substr(
annotation.startPos + offset,
annotation.endPos - annotation.startPos + 1
);
// if is function name itself, replace with qualified name
if (utility::containsElement(file->getSourceLocationById(annotation.locationId)->getTokenIds(), node.id) &&
text.size() <= nameHierarchy.getRawName().size())
{
std::wstring name = nameHierarchy.getQualifiedName();
offset = name.size() - text.size();
code = code.replace(annotation.startPos, annotation.endPos - annotation.startPos + 1, name);
text = name;
}
else
{
text = utility::convertWhiteSpacesToSingleSpaces(text);
}
annotatedTexts.push_back(std::make_pair(annotation.locationId, text));
}
// format
code = utility::convertWhiteSpacesToSingleSpaces(code);
snippet.code = utility::breakSignature(code, 50, ApplicationSettings::getInstance()->getCodeTabWidth());
// create source locations for annotations via stored texts
size_t pos = 0;
for (const std::pair<Id, std::wstring>& p : annotatedTexts)
{
pos = snippet.code.find(p.second, pos);
if (pos != std::wstring::npos)
{
SourceLocation* loc = file->getSourceLocationById(p.first);
snippet.locationFile->addSourceLocation(
loc->getType(), loc->getLocationId(), loc->getTokenIds(),
1, pos + 1, 1, pos + p.second.size()
);
pos += p.second.size();
}
}
return snippet;
}
// otherwise augment the name with signature with locations for type usages
snippet.code = utility::breakSignature(
nameHierarchy.getSignature().getPrefix(),
nameHierarchy.getQualifiedName(),