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:
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user