[IDE] Pass a SourceRange instead of a CharSourceRange in SemaAnnotator::passReference

Most `SemaAnnotator`s don’t actually care about the char source range. Instead, they only care about the start location of the reference, which is also included in `SourceRange`. Computing a `CharSourceRange` from a `SourceRange` is kind of expensive because it needs to start a new lexer.

To avoid this overhead, pass `SourceRange` to `SemaAnnotator::passReference` and related functions and let the clients compute the `CharSourceRange` when needed.

This reduces the overhead of index-while-building by about 10%.
This commit is contained in:
Alex Hoppen
2025-06-04 12:34:07 +02:00
parent 9ae142c9d3
commit c6c40de73d
10 changed files with 95 additions and 88 deletions

View File

@@ -140,7 +140,7 @@ public:
/// refers to. /// refers to.
/// \param ExtTyRef this is set when the entity is a reference to a type loc /// \param ExtTyRef this is set when the entity is a reference to a type loc
/// in \c ExtensionDecl. /// in \c ExtensionDecl.
virtual bool visitDeclReference(ValueDecl *D, CharSourceRange Range, virtual bool visitDeclReference(ValueDecl *D, SourceRange Range,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
Type T, ReferenceMetaData Data); Type T, ReferenceMetaData Data);
@@ -156,7 +156,7 @@ public:
/// \param Data whether this is a read, write or read/write access, etc. /// \param Data whether this is a read, write or read/write access, etc.
/// \param IsOpenBracket this is \c true when the method is called on an /// \param IsOpenBracket this is \c true when the method is called on an
/// open bracket. /// open bracket.
virtual bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range, virtual bool visitSubscriptReference(ValueDecl *D, SourceRange Range,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket); bool IsOpenBracket);
@@ -167,7 +167,7 @@ public:
/// \param D the referenced decl. /// \param D the referenced decl.
/// \param Range the source range of the source reference. /// \param Range the source range of the source reference.
/// \param Data whether this is a read, write or read/write access, etc. /// \param Data whether this is a read, write or read/write access, etc.
virtual bool visitCallAsFunctionReference(ValueDecl *D, CharSourceRange Range, virtual bool visitCallAsFunctionReference(ValueDecl *D, SourceRange Range,
ReferenceMetaData Data); ReferenceMetaData Data);
/// This method is called for each keyword argument in a call expression. /// This method is called for each keyword argument in a call expression.

View File

@@ -829,9 +829,9 @@ bool swift::emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
class ObjcMethodReferenceCollector: public SourceEntityWalker { class ObjcMethodReferenceCollector: public SourceEntityWalker {
unsigned CurrentFileID; unsigned CurrentFileID;
llvm::DenseMap<const clang::ObjCMethodDecl*, unsigned> results; llvm::DenseMap<const clang::ObjCMethodDecl*, unsigned> results;
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, ExtensionDecl *ExtTyRef, Type T,
Type T, ReferenceMetaData Data) override { ReferenceMetaData Data) override {
if (!Range.isValid()) if (!Range.isValid())
return true; return true;
if (auto *clangD = dyn_cast_or_null<clang::ObjCMethodDecl>(D->getClangDecl())) if (auto *clangD = dyn_cast_or_null<clang::ObjCMethodDecl>(D->getClangDecl()))

View File

@@ -89,8 +89,8 @@ private:
bool walkToDeclPost(Decl *D) override; bool walkToDeclPost(Decl *D) override;
bool walkToStmtPre(Stmt *S) override; bool walkToStmtPre(Stmt *S) override;
bool walkToStmtPost(Stmt *S) override; bool walkToStmtPost(Stmt *S) override;
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) override; ReferenceMetaData Data) override;
bool visitCallArgName(Identifier Name, CharSourceRange Range, bool visitCallArgName(Identifier Name, CharSourceRange Range,
ValueDecl *D) override; ValueDecl *D) override;
@@ -105,7 +105,7 @@ private:
std::optional<ReferenceMetaData> Data = std::nullopt); std::optional<ReferenceMetaData> Data = std::nullopt);
bool tryResolve(ModuleEntity Mod, SourceLoc Loc); bool tryResolve(ModuleEntity Mod, SourceLoc Loc);
bool tryResolve(Stmt *St); bool tryResolve(Stmt *St);
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range, bool visitSubscriptReference(ValueDecl *D, SourceRange Range,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket) override; bool IsOpenBracket) override;
}; };
@@ -210,7 +210,7 @@ bool CursorInfoResolver::tryResolve(Stmt *St) {
} }
bool CursorInfoResolver::visitSubscriptReference(ValueDecl *D, bool CursorInfoResolver::visitSubscriptReference(ValueDecl *D,
CharSourceRange Range, SourceRange Range,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket) { bool IsOpenBracket) {
// We should treat both open and close brackets equally // We should treat both open and close brackets equally
@@ -301,8 +301,7 @@ bool CursorInfoResolver::walkToStmtPost(Stmt *S) {
return true; return true;
} }
bool CursorInfoResolver::visitDeclReference(ValueDecl *D, bool CursorInfoResolver::visitDeclReference(ValueDecl *D, SourceRange Range,
CharSourceRange Range,
TypeDecl *CtorTyRef, TypeDecl *CtorTyRef,
ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) { ReferenceMetaData Data) {
@@ -310,7 +309,8 @@ bool CursorInfoResolver::visitDeclReference(ValueDecl *D,
return false; return false;
if (Data.isImplicit || !Range.isValid()) if (Data.isImplicit || !Range.isValid())
return true; return true;
return !tryResolve(D, CtorTyRef, ExtTyRef, Range.getStart(), /*IsRef=*/true, T, Data); return !tryResolve(D, CtorTyRef, ExtTyRef, Range.Start, /*IsRef=*/true, T,
Data);
} }
static bool isCursorOn(Expr *E, SourceLoc Loc) { static bool isCursorOn(Expr *E, SourceLoc Loc) {
@@ -461,8 +461,8 @@ class RangeResolver : public SourceEntityWalker {
bool walkToStmtPost(Stmt *S) override; bool walkToStmtPost(Stmt *S) override;
bool walkToDeclPre(Decl *D, CharSourceRange Range) override; bool walkToDeclPre(Decl *D, CharSourceRange Range) override;
bool walkToDeclPost(Decl *D) override; bool walkToDeclPost(Decl *D) override;
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) override; ReferenceMetaData Data) override;
ResolvedRangeInfo moveArrayToASTContext(ResolvedRangeInfo Info); ResolvedRangeInfo moveArrayToASTContext(ResolvedRangeInfo Info);
public: public:
@@ -799,12 +799,13 @@ public:
Impl->analyzeDecl(D); Impl->analyzeDecl(D);
return true; return true;
} }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
ReferenceMetaData Data) override { Type T, ReferenceMetaData Data) override {
Impl->analyzeDeclRef(D, Range.getStart(), T, Data); Impl->analyzeDeclRef(D, Range.Start, T, Data);
return true; return true;
} }
public: public:
CompleteWalker(Implementation *Impl) : Impl(Impl) {} CompleteWalker(Implementation *Impl) : Impl(Impl) {}
}; };
@@ -813,11 +814,11 @@ public:
/// decls in the range is referenced after it. /// decls in the range is referenced after it.
class FurtherReferenceWalker : public SourceEntityWalker { class FurtherReferenceWalker : public SourceEntityWalker {
Implementation *Impl; Implementation *Impl;
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
ReferenceMetaData Data) override { Type T, ReferenceMetaData Data) override {
// If the reference is after the given range, continue logic. // If the reference is after the given range, continue logic.
if (!Impl->SM.isBeforeInBuffer(Impl->End, Range.getStart())) if (!Impl->SM.isBeforeInBuffer(Impl->End, Range.Start))
return true; return true;
// If the referenced decl is declared in the range, than the declared decl // If the referenced decl is declared in the range, than the declared decl
@@ -829,6 +830,7 @@ public:
} }
return true; return true;
} }
public: public:
FurtherReferenceWalker(Implementation *Impl) : Impl(Impl) {} FurtherReferenceWalker(Implementation *Impl) : Impl(Impl) {}
}; };
@@ -1140,11 +1142,11 @@ bool RangeResolver::walkToDeclPost(Decl *D) {
return !Impl->hasResult(); return !Impl->hasResult();
} }
bool RangeResolver::visitDeclReference(ValueDecl *D, SourceRange Range,
bool RangeResolver:: TypeDecl *CtorTyRef,
visitDeclReference(ValueDecl *D, CharSourceRange Range, TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T,
ExtensionDecl *ExtTyRef, Type T, ReferenceMetaData Data) { ReferenceMetaData Data) {
Impl->analyzeDeclRef(D, Range.getStart(), T, Data); Impl->analyzeDeclRef(D, Range.Start, T, Data);
return true; return true;
} }

View File

@@ -851,28 +851,19 @@ bool SemaAnnotator::passModulePathElements(
bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc, bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket) { bool IsOpenBracket) {
CharSourceRange Range = Loc.isValid() return SEWalker.visitSubscriptReference(D, Loc, Data, IsOpenBracket);
? CharSourceRange(Loc, 1)
: CharSourceRange();
return SEWalker.visitSubscriptReference(D, Range, Data, IsOpenBracket);
} }
bool SemaAnnotator::passCallAsFunctionReference(ValueDecl *D, SourceLoc Loc, bool SemaAnnotator::passCallAsFunctionReference(ValueDecl *D, SourceLoc Loc,
ReferenceMetaData Data) { ReferenceMetaData Data) {
CharSourceRange Range = return SEWalker.visitCallAsFunctionReference(D, Loc, Data);
Loc.isValid() ? CharSourceRange(Loc, 1) : CharSourceRange();
return SEWalker.visitCallAsFunctionReference(D, Range, Data);
} }
bool SemaAnnotator:: bool SemaAnnotator::
passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data) { passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data) {
SourceManager &SM = D->getASTContext().SourceMgr; SourceManager &SM = D->getASTContext().SourceMgr;
SourceLoc BaseStart = Loc.getBaseNameLoc(), BaseEnd = BaseStart; SourceLoc BaseStart = Loc.getBaseNameLoc(), BaseEnd = BaseStart;
if (BaseStart.isValid() && SM.extractText({BaseStart, 1}) == "`") return passReference(D, Ty, Loc.getBaseNameLoc(), Loc.getSourceRange(), Data);
BaseEnd = Lexer::getLocForEndOfToken(SM, BaseStart.getAdvancedLoc(1));
return passReference(D, Ty, BaseStart, {BaseStart, BaseEnd}, Data);
} }
bool SemaAnnotator:: bool SemaAnnotator::
@@ -917,12 +908,7 @@ passReference(ValueDecl *D, Type Ty, SourceLoc BaseNameLoc, SourceRange Range,
} }
} }
CharSourceRange CharRange = return SEWalker.visitDeclReference(D, Range, CtorTyRef, ExtDecl, Ty, Data);
Lexer::getCharSourceRangeFromSourceRange(D->getASTContext().SourceMgr,
Range);
return SEWalker.visitDeclReference(D, CharRange, CtorTyRef, ExtDecl, Ty,
Data);
} }
bool SemaAnnotator::passReference(ModuleEntity Mod, bool SemaAnnotator::passReference(ModuleEntity Mod,
@@ -1023,7 +1009,7 @@ bool SourceEntityWalker::walk(ASTNode N) {
llvm_unreachable("unsupported AST node"); llvm_unreachable("unsupported AST node");
} }
bool SourceEntityWalker::visitDeclReference(ValueDecl *D, CharSourceRange Range, bool SourceEntityWalker::visitDeclReference(ValueDecl *D, SourceRange Range,
TypeDecl *CtorTyRef, TypeDecl *CtorTyRef,
ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) { ReferenceMetaData Data) {
@@ -1031,7 +1017,7 @@ bool SourceEntityWalker::visitDeclReference(ValueDecl *D, CharSourceRange Range,
} }
bool SourceEntityWalker::visitSubscriptReference(ValueDecl *D, bool SourceEntityWalker::visitSubscriptReference(ValueDecl *D,
CharSourceRange Range, SourceRange Range,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket) { bool IsOpenBracket) {
// Most of the clients treat subscript reference the same way as a // Most of the clients treat subscript reference the same way as a
@@ -1043,7 +1029,7 @@ bool SourceEntityWalker::visitSubscriptReference(ValueDecl *D,
} }
bool SourceEntityWalker::visitCallAsFunctionReference(ValueDecl *D, bool SourceEntityWalker::visitCallAsFunctionReference(ValueDecl *D,
CharSourceRange Range, SourceRange Range,
ReferenceMetaData Data) { ReferenceMetaData Data) {
return true; return true;
} }

View File

@@ -33,6 +33,7 @@
#include "swift/IDE/SourceEntityWalker.h" #include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/Utils.h" #include "swift/IDE/Utils.h"
#include "swift/Markup/Markup.h" #include "swift/Markup/Markup.h"
#include "swift/Parse/Lexer.h"
#include "swift/Sema/IDETypeChecking.h" #include "swift/Sema/IDETypeChecking.h"
#include "llvm/ADT/APInt.h" #include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@@ -875,10 +876,10 @@ private:
llvm_unreachable("Can't find the generic parameter in the extended type"); llvm_unreachable("Can't find the generic parameter in the extended type");
} }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) override { ReferenceMetaData Data) override {
SourceLoc Loc = Range.getStart(); SourceLoc Loc = Range.Start;
if (Loc.isInvalid() || isSuppressed(Loc)) if (Loc.isInvalid() || isSuppressed(Loc))
return true; return true;
@@ -918,15 +919,18 @@ private:
// report an occurrence of `foo` in `_foo` and '$foo'). // report an occurrence of `foo` in `_foo` and '$foo').
if (auto *VD = dyn_cast<VarDecl>(D)) { if (auto *VD = dyn_cast<VarDecl>(D)) {
if (auto *Wrapped = VD->getOriginalWrappedProperty()) { if (auto *Wrapped = VD->getOriginalWrappedProperty()) {
assert(Range.getByteLength() > 1); CharSourceRange CharRange = Lexer::getCharSourceRangeFromSourceRange(
if (Range.str().front() == '`') { D->getASTContext().SourceMgr, Range);
assert(Range.getByteLength() > 3); assert(CharRange.getByteLength() > 1);
assert(Range.str().starts_with("`_") || if (CharRange.str().front() == '`') {
Range.str().starts_with("`$")); assert(CharRange.getByteLength() > 3);
assert(CharRange.str().starts_with("`_") ||
CharRange.str().starts_with("`$"));
auto AfterBacktick = Loc.getAdvancedLoc(2); auto AfterBacktick = Loc.getAdvancedLoc(2);
reportRef(Wrapped, AfterBacktick, Info, std::nullopt); reportRef(Wrapped, AfterBacktick, Info, std::nullopt);
} else { } else {
assert(Range.str().front() == '_' || Range.str().front() == '$'); assert(CharRange.str().front() == '_' ||
CharRange.str().front() == '$');
auto AfterDollar = Loc.getAdvancedLoc(1); auto AfterDollar = Loc.getAdvancedLoc(1);
reportRef(Wrapped, AfterDollar, Info, std::nullopt); reportRef(Wrapped, AfterDollar, Info, std::nullopt);
} }
@@ -960,7 +964,7 @@ private:
return finishSourceEntity(Info.symInfo, Info.roles); return finishSourceEntity(Info.symInfo, Info.roles);
} }
bool visitCallAsFunctionReference(ValueDecl *D, CharSourceRange Range, bool visitCallAsFunctionReference(ValueDecl *D, SourceRange Range,
ReferenceMetaData Data) override { ReferenceMetaData Data) override {
// Index implicit callAsFunction reference. // Index implicit callAsFunction reference.
return visitDeclReference(D, Range, /*CtorTyRef*/ nullptr, return visitDeclReference(D, Range, /*CtorTyRef*/ nullptr,

View File

@@ -468,16 +468,18 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
} }
} }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, ExtensionDecl *ExtTyRef, Type T,
Type T, ReferenceMetaData Data) override { ReferenceMetaData Data) override {
CharSourceRange CharRange = Lexer::getCharSourceRangeFromSourceRange(
D->getASTContext().SourceMgr, Range);
if (Data.isImplicit) if (Data.isImplicit)
return true; return true;
for (auto *Item: getRelatedDiffItems(CtorTyRef ? CtorTyRef: D)) { for (auto *Item: getRelatedDiffItems(CtorTyRef ? CtorTyRef: D)) {
std::string RepText; std::string RepText;
if (isSimpleReplacement(Item, isDotMember(Range), RepText)) { if (isSimpleReplacement(Item, isDotMember(CharRange), RepText)) {
Editor.replace(Range, RepText); Editor.replace(CharRange, RepText);
return true; return true;
} }
} }
@@ -488,11 +490,12 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
ValueDecl *Target; ValueDecl *Target;
CharSourceRange Result; CharSourceRange Result;
ReferenceCollector(ValueDecl* Target) : Target(Target) {} ReferenceCollector(ValueDecl* Target) : Target(Target) {}
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
Type T, ReferenceMetaData Data) override { Type T, ReferenceMetaData Data) override {
if (D == Target && !Data.isImplicit && Range.isValid()) { if (D == Target && !Data.isImplicit && Range.isValid()) {
Result = Range; Result = Lexer::getCharSourceRangeFromSourceRange(
D->getASTContext().SourceMgr, Range);
return false; return false;
} }
return true; return true;

View File

@@ -26,8 +26,8 @@ struct ReferenceCollector : public SourceEntityWalker {
SmallVector<ValueDecl *, 4> References; SmallVector<ValueDecl *, 4> References;
ReferenceCollector(Expr *E) { walk(E); } ReferenceCollector(Expr *E) { walk(E); }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) override { ReferenceMetaData Data) override {
References.emplace_back(D); References.emplace_back(D);
return true; return true;

View File

@@ -1203,21 +1203,24 @@ public:
return true; return true;
} }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type Ty, ExtensionDecl *ExtTyRef, Type Ty,
ReferenceMetaData Data) override { ReferenceMetaData Data) override {
if (Data.isImplicit || !Range.isValid()) if (Data.isImplicit || !Range.isValid())
return true; return true;
// Ignore things that don't come from this buffer. // Ignore things that don't come from this buffer.
if (!SM.getRangeForBuffer(BufferID).contains(Range.getStart())) if (!SM.getRangeForBuffer(BufferID).contains(Range.Start))
return true; return true;
unsigned StartOffset = getOffset(Range.getStart()); CharSourceRange CharRange = Lexer::getCharSourceRangeFromSourceRange(
References.emplace_back(D, StartOffset, Range.getByteLength(), Ty); D->getASTContext().SourceMgr, Range);
unsigned StartOffset = getOffset(CharRange.getStart());
References.emplace_back(D, StartOffset, CharRange.getByteLength(), Ty);
return true; return true;
} }
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range, bool visitSubscriptReference(ValueDecl *D, SourceRange Range,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket) override { bool IsOpenBracket) override {
// Treat both open and close brackets equally // Treat both open and close brackets equally

View File

@@ -990,8 +990,8 @@ public:
} }
} }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) override { ReferenceMetaData Data) override {
if (Data.isImplicit) if (Data.isImplicit)
return true; return true;
@@ -1004,9 +1004,12 @@ public:
if (D->isUnavailable()) if (D->isUnavailable())
return true; return true;
CharSourceRange CharRange = Lexer::getCharSourceRangeFromSourceRange(
D->getASTContext().SourceMgr, Range);
auto &SM = D->getASTContext().SourceMgr; auto &SM = D->getASTContext().SourceMgr;
if (D == D->getASTContext().getOptionalNoneDecl() && if (D == D->getASTContext().getOptionalNoneDecl() &&
SM.extractText(Range, BufferID) == "nil") { SM.extractText(CharRange, BufferID) == "nil") {
// If a 'nil' literal occurs in a swift-case statement, it gets replaced // If a 'nil' literal occurs in a swift-case statement, it gets replaced
// by a reference to 'Optional.none' in the AST. We want to continue // by a reference to 'Optional.none' in the AST. We want to continue
// highlighting 'nil' as a keyword and not as an enum element. // highlighting 'nil' as a keyword and not as an enum element.
@@ -1015,11 +1018,11 @@ public:
if (CtorTyRef) if (CtorTyRef)
D = CtorTyRef; D = CtorTyRef;
annotate(D, /*IsRef=*/true, Range); annotate(D, /*IsRef=*/true, CharRange);
return true; return true;
} }
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range, bool visitSubscriptReference(ValueDecl *D, SourceRange Range,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket) override { bool IsOpenBracket) override {
// We should treat both open and close brackets equally // We should treat both open and close brackets equally

View File

@@ -2342,15 +2342,19 @@ private:
return true; return true;
} }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type Ty, ExtensionDecl *ExtTyRef, Type Ty,
ReferenceMetaData Data) override { ReferenceMetaData Data) override {
if (!Data.isImplicit) if (Data.isImplicit) {
annotateSourceEntity({ Range, D, CtorTyRef, /*IsRef=*/true }); return true;
}
CharSourceRange CharRange = Lexer::getCharSourceRangeFromSourceRange(
D->getASTContext().SourceMgr, Range);
annotateSourceEntity({CharRange, D, CtorTyRef, /*IsRef=*/true});
return true; return true;
} }
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range, bool visitSubscriptReference(ValueDecl *D, SourceRange Range,
ReferenceMetaData Data, ReferenceMetaData Data,
bool IsOpenBracket) override { bool IsOpenBracket) override {
return visitDeclReference(D, Range, nullptr, nullptr, Type(), Data); return visitDeclReference(D, Range, nullptr, nullptr, Type(), Data);
@@ -3909,11 +3913,13 @@ public:
return true; return true;
} }
bool visitDeclReference(ValueDecl *D, CharSourceRange Range, bool visitDeclReference(ValueDecl *D, SourceRange Range, TypeDecl *CtorTyRef,
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T, ExtensionDecl *ExtTyRef, Type T,
ReferenceMetaData Data) override { ReferenceMetaData Data) override {
CharSourceRange CharRange = Lexer::getCharSourceRangeFromSourceRange(
D->getASTContext().SourceMgr, Range);
if (SeenDecls.insert(D).second) if (SeenDecls.insert(D).second)
tryDemangleDecl(D, Range, /*isRef=*/true); tryDemangleDecl(D, CharRange, /*isRef=*/true);
if (T) { if (T) {
T = T->getRValueType(); T = T->getRValueType();
@@ -3921,7 +3927,7 @@ public:
(NestedDCs.empty() (NestedDCs.empty()
? D->getDeclContext() ? D->getDeclContext()
: NestedDCs.back()), : NestedDCs.back()),
Range); CharRange);
} }
return true; return true;
} }