Skip to content

Commit 8e857d5

Browse files
authored
Merge pull request #62292 from ahoppen/ahoppen/solver-based-cursor-info-prep
[SourceKit] Preparation for solver-based cursor info
2 parents 635e34b + 8af4db2 commit 8e857d5

24 files changed

+583
-236
lines changed

include/swift/AST/Stmt.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ class BraceStmt final : public Stmt,
171171
SourceLoc getStartLoc() const;
172172
SourceLoc getEndLoc() const;
173173

174+
SourceLoc getContentStartLoc() const;
175+
SourceLoc getContentEndLoc() const;
176+
/// The range of the brace statement without the braces.
177+
SourceRange getContentRange() const {
178+
return {getContentStartLoc(), getContentEndLoc()};
179+
}
180+
174181
bool empty() const { return getNumElements() == 0; }
175182
unsigned getNumElements() const { return Bits.BraceStmt.NumElements; }
176183

include/swift/IDE/Utils.h

Lines changed: 171 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -128,71 +128,200 @@ enum class CursorInfoKind {
128128
StmtStart,
129129
};
130130

131+
/// Base class of more specialized \c ResolvedCursorInfos that also represents
132+
/// and \c Invalid cursor info.
133+
/// Subclasses of \c ResolvedCursorInfo cannot add new stored properies because
134+
/// \c ResolvedCursorInfo is being passed around as its base class and thus any
135+
/// properties in subclasses would get lost.
131136
struct ResolvedCursorInfo {
137+
protected:
132138
CursorInfoKind Kind = CursorInfoKind::Invalid;
133139
SourceFile *SF = nullptr;
134140
SourceLoc Loc;
135-
ValueDecl *ValueD = nullptr;
136-
TypeDecl *CtorTyRef = nullptr;
137-
ExtensionDecl *ExtTyRef = nullptr;
138-
/// Declarations that were shadowed by \c ValueD using a shorthand syntax that
139-
/// names both the newly declared variable and the referenced variable by the
140-
/// same identifier in the source text. This includes shorthand closure
141-
/// captures (`[foo]`) and shorthand if captures
142-
/// (`if let foo {`).
143-
/// Decls that are shadowed using shorthand syntax should be reported as
144-
/// additional cursor info results.
145-
SmallVector<ValueDecl *, 2> ShorthandShadowedDecls;
146-
ModuleEntity Mod;
147-
bool IsRef = true;
148-
bool IsKeywordArgument = false;
149-
Type Ty;
150-
Type ContainerType;
151-
Stmt *TrailingStmt = nullptr;
152-
Expr *TrailingExpr = nullptr;
153-
/// It this is a ref, whether it is "dynamic". See \c ide::isDynamicRef.
154-
bool IsDynamic = false;
155-
/// If this is a dynamic ref, the types of the base (multiple in the case of
156-
/// protocol composition).
157-
SmallVector<NominalTypeDecl *, 1> ReceiverTypes;
158141

142+
// Technically, these structs could form a union (because only one of them is
143+
// active at a time). But I had issues with C++ complaining about copy
144+
// constructors and gave up. At the moment it's only wasting 3 words for non
145+
// ValueRef data.
146+
struct {
147+
ValueDecl *ValueD = nullptr;
148+
TypeDecl *CtorTyRef = nullptr;
149+
ExtensionDecl *ExtTyRef = nullptr;
150+
bool IsRef = true;
151+
Type Ty;
152+
Type ContainerType;
153+
bool IsKeywordArgument = false;
154+
/// It this is a ref, whether it is "dynamic". See \c ide::isDynamicRef.
155+
bool IsDynamic = false;
156+
/// If this is a dynamic ref, the types of the base (multiple in the case of
157+
/// protocol composition).
158+
SmallVector<NominalTypeDecl *> ReceiverTypes;
159+
/// Declarations that were shadowed by \c ValueD using a shorthand syntax
160+
/// that names both the newly declared variable and the referenced variable
161+
/// by the same identifier in the source text. This includes shorthand
162+
/// closure captures (`[foo]`) and shorthand if captures
163+
/// (`if let foo {`).
164+
/// Decls that are shadowed using shorthand syntax should be reported as
165+
/// additional cursor info results.
166+
SmallVector<ValueDecl *> ShorthandShadowedDecls;
167+
} ValueRefInfo;
168+
struct {
169+
ModuleEntity Mod;
170+
} ModuleRefInfo;
171+
struct {
172+
Expr *TrailingExpr = nullptr;
173+
} ExprStartInfo;
174+
struct {
175+
Stmt *TrailingStmt = nullptr;
176+
} StmtStartInfo;
177+
178+
public:
159179
ResolvedCursorInfo() = default;
160180
ResolvedCursorInfo(SourceFile *SF) : SF(SF) {}
161181

162-
ValueDecl *typeOrValue() { return CtorTyRef ? CtorTyRef : ValueD; }
182+
CursorInfoKind getKind() const { return Kind; }
183+
184+
SourceFile *getSourceFile() const { return SF; }
185+
186+
SourceLoc getLoc() const { return Loc; }
187+
void setLoc(SourceLoc Loc) { this->Loc = Loc; }
163188

164189
friend bool operator==(const ResolvedCursorInfo &lhs,
165190
const ResolvedCursorInfo &rhs) {
166191
return lhs.SF == rhs.SF &&
167192
lhs.Loc.getOpaquePointerValue() == rhs.Loc.getOpaquePointerValue();
168193
}
169194

170-
void setValueRef(ValueDecl *ValueD, TypeDecl *CtorTyRef,
171-
ExtensionDecl *ExtTyRef, bool IsRef,
172-
Type Ty, Type ContainerType) {
195+
bool isValid() const { return !isInvalid(); }
196+
bool isInvalid() const { return Kind == CursorInfoKind::Invalid; }
197+
};
198+
199+
struct ResolvedValueRefCursorInfo : public ResolvedCursorInfo {
200+
// IMPORTANT: Don't add stored properties here. See comment on
201+
// ResolvedCursorInfo.
202+
203+
ResolvedValueRefCursorInfo() = default;
204+
explicit ResolvedValueRefCursorInfo(const ResolvedCursorInfo &Base,
205+
ValueDecl *ValueD, TypeDecl *CtorTyRef,
206+
ExtensionDecl *ExtTyRef, bool IsRef,
207+
Type Ty, Type ContainerType)
208+
: ResolvedCursorInfo(Base) {
209+
assert(Base.getKind() == CursorInfoKind::Invalid &&
210+
"Can only specialize from invalid");
173211
Kind = CursorInfoKind::ValueRef;
174-
this->ValueD = ValueD;
175-
this->CtorTyRef = CtorTyRef;
176-
this->ExtTyRef = ExtTyRef;
177-
this->IsRef = IsRef;
178-
this->Ty = Ty;
179-
this->ContainerType = ContainerType;
212+
ValueRefInfo.ValueD = ValueD;
213+
ValueRefInfo.CtorTyRef = CtorTyRef;
214+
ValueRefInfo.ExtTyRef = ExtTyRef;
215+
ValueRefInfo.IsRef = IsRef;
216+
ValueRefInfo.Ty = Ty;
217+
ValueRefInfo.ContainerType = ContainerType;
218+
}
219+
220+
ValueDecl *getValueD() const { return ValueRefInfo.ValueD; }
221+
void setValueD(ValueDecl *ValueD) { ValueRefInfo.ValueD = ValueD; }
222+
223+
ExtensionDecl *getExtTyRef() const { return ValueRefInfo.ExtTyRef; }
224+
225+
TypeDecl *getCtorTyRef() const { return ValueRefInfo.CtorTyRef; }
226+
227+
bool isRef() const { return ValueRefInfo.IsRef; }
228+
void setIsRef(bool IsRef) { ValueRefInfo.IsRef = IsRef; }
229+
230+
Type getType() const { return ValueRefInfo.Ty; }
231+
232+
Type getContainerType() const { return ValueRefInfo.ContainerType; }
233+
void setContainerType(Type Ty) { ValueRefInfo.ContainerType = Ty; }
234+
235+
bool isKeywordArgument() const { return ValueRefInfo.IsKeywordArgument; }
236+
void setIsKeywordArgument(bool IsKeywordArgument) {
237+
ValueRefInfo.IsKeywordArgument = IsKeywordArgument;
238+
}
239+
240+
bool isDynamic() const { return ValueRefInfo.IsDynamic; }
241+
void setIsDynamic(bool IsDynamic) { ValueRefInfo.IsDynamic = IsDynamic; }
242+
243+
ArrayRef<NominalTypeDecl *> getReceiverTypes() const {
244+
return ValueRefInfo.ReceiverTypes;
245+
}
246+
void setReceiverTypes(const SmallVector<NominalTypeDecl *> &ReceiverTypes) {
247+
ValueRefInfo.ReceiverTypes = ReceiverTypes;
248+
}
249+
250+
ArrayRef<ValueDecl *> getShorthandShadowedDecls() const {
251+
return ValueRefInfo.ShorthandShadowedDecls;
252+
};
253+
void setShorthandShadowedDecls(
254+
const SmallVector<ValueDecl *> &ShorthandShadowedDecls) {
255+
ValueRefInfo.ShorthandShadowedDecls = ShorthandShadowedDecls;
256+
};
257+
258+
ValueDecl *typeOrValue() {
259+
return ValueRefInfo.CtorTyRef ? ValueRefInfo.CtorTyRef
260+
: ValueRefInfo.ValueD;
180261
}
181-
void setModuleRef(ModuleEntity Mod) {
262+
263+
static bool classof(const ResolvedCursorInfo *Info) {
264+
return Info->getKind() == CursorInfoKind::ValueRef;
265+
}
266+
};
267+
268+
struct ResolvedModuleRefCursorInfo : public ResolvedCursorInfo {
269+
// IMPORTANT: Don't add stored properties here. See comment on
270+
// ResolvedCursorInfo.
271+
272+
ResolvedModuleRefCursorInfo(const ResolvedCursorInfo &Base, ModuleEntity Mod)
273+
: ResolvedCursorInfo(Base) {
274+
assert(Base.getKind() == CursorInfoKind::Invalid &&
275+
"Can only specialize from invalid");
182276
Kind = CursorInfoKind::ModuleRef;
183-
this->Mod = Mod;
277+
ModuleRefInfo.Mod = Mod;
184278
}
185-
void setTrailingStmt(Stmt *TrailingStmt) {
186-
Kind = CursorInfoKind::StmtStart;
187-
this->TrailingStmt = TrailingStmt;
279+
280+
ModuleEntity getMod() const { return ModuleRefInfo.Mod; }
281+
282+
static bool classof(const ResolvedCursorInfo *Info) {
283+
return Info->getKind() == CursorInfoKind::ModuleRef;
188284
}
189-
void setTrailingExpr(Expr* TrailingExpr) {
285+
};
286+
287+
struct ResolvedExprStartCursorInfo : public ResolvedCursorInfo {
288+
// IMPORTANT: Don't add stored properties here. See comment on
289+
// ResolvedCursorInfo.
290+
291+
ResolvedExprStartCursorInfo(const ResolvedCursorInfo &Base,
292+
Expr *TrailingExpr)
293+
: ResolvedCursorInfo(Base) {
294+
assert(Base.getKind() == CursorInfoKind::Invalid &&
295+
"Can only specialize from invalid");
190296
Kind = CursorInfoKind::ExprStart;
191-
this->TrailingExpr = TrailingExpr;
297+
ExprStartInfo.TrailingExpr = TrailingExpr;
192298
}
193299

194-
bool isValid() const { return !isInvalid(); }
195-
bool isInvalid() const { return Kind == CursorInfoKind::Invalid; }
300+
Expr *getTrailingExpr() const { return ExprStartInfo.TrailingExpr; }
301+
302+
static bool classof(const ResolvedCursorInfo *Info) {
303+
return Info->getKind() == CursorInfoKind::ExprStart;
304+
}
305+
};
306+
307+
struct ResolvedStmtStartCursorInfo : public ResolvedCursorInfo {
308+
// IMPORTANT: Don't add stored properties here. See comment on
309+
// ResolvedCursorInfo.
310+
311+
ResolvedStmtStartCursorInfo(const ResolvedCursorInfo &Base,
312+
Stmt *TrailingStmt)
313+
: ResolvedCursorInfo(Base) {
314+
assert(Base.getKind() == CursorInfoKind::Invalid &&
315+
"Can only specialize from invalid");
316+
Kind = CursorInfoKind::StmtStart;
317+
StmtStartInfo.TrailingStmt = TrailingStmt;
318+
}
319+
320+
Stmt *getTrailingStmt() const { return StmtStartInfo.TrailingStmt; }
321+
322+
static bool classof(const ResolvedCursorInfo *Info) {
323+
return Info->getKind() == CursorInfoKind::StmtStart;
324+
}
196325
};
197326

198327
void simple_display(llvm::raw_ostream &out, const ResolvedCursorInfo &info);

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class CodeCompletionCallbacks {
254254

255255
/// Signals that the AST for the all the delayed-parsed code was
256256
/// constructed. No \c complete*() callbacks will be done after this.
257-
virtual void doneParsing() = 0;
257+
virtual void doneParsing(SourceFile *SrcFile) = 0;
258258
};
259259

260260
/// A factory to create instances of \c CodeCompletionCallbacks.

include/swift/Sema/IDETypeChecking.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ namespace swift {
164164
constraints::SolutionApplicationTarget &target, bool needsPrecheck,
165165
llvm::function_ref<void(const constraints::Solution &)> callback);
166166

167+
/// Thunk around \c TypeChecker::resolveDeclRefExpr to make it available to
168+
/// \c swift::ide
169+
Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context,
170+
bool replaceInvalidRefsWithErrors);
171+
167172
LookupResult
168173
lookupSemanticMember(DeclContext *DC, Type ty, DeclName name);
169174

@@ -339,12 +344,17 @@ namespace swift {
339344
/// these shorthand shadows.
340345
/// The first element in the pair is the implicitly declared variable and the
341346
/// second variable is the shadowed one.
347+
/// If a \c DeclContext is passed, it is used to resolve any
348+
/// \c UnresolvedDeclRef that a shorthand shadow may refer to.
342349
SmallVector<std::pair<ValueDecl *, ValueDecl *>, 1>
343-
getShorthandShadows(CaptureListExpr *CaptureList);
350+
getShorthandShadows(CaptureListExpr *CaptureList, DeclContext *DC = nullptr);
344351

345352
/// Same as above but for shorthand `if let foo {` syntax.
353+
/// If a \c DeclContext is passed, it is used to resolve any
354+
/// \c UnresolvedDeclRef that a shorthand shadow may refer to.
346355
SmallVector<std::pair<ValueDecl *, ValueDecl *>, 1>
347-
getShorthandShadows(LabeledConditionalStmt *CondStmt);
356+
getShorthandShadows(LabeledConditionalStmt *CondStmt,
357+
DeclContext *DC = nullptr);
348358
}
349359

350360
#endif

lib/AST/Stmt.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,17 @@ SourceLoc BraceStmt::getStartLoc() const {
160160
if (LBLoc) {
161161
return LBLoc;
162162
}
163+
return getContentStartLoc();
164+
}
165+
166+
SourceLoc BraceStmt::getEndLoc() const {
167+
if (RBLoc) {
168+
return RBLoc;
169+
}
170+
return getContentEndLoc();
171+
}
172+
173+
SourceLoc BraceStmt::getContentStartLoc() const {
163174
for (auto elt : getElements()) {
164175
if (auto loc = elt.getStartLoc()) {
165176
return loc;
@@ -168,10 +179,7 @@ SourceLoc BraceStmt::getStartLoc() const {
168179
return SourceLoc();
169180
}
170181

171-
SourceLoc BraceStmt::getEndLoc() const {
172-
if (RBLoc) {
173-
return RBLoc;
174-
}
182+
SourceLoc BraceStmt::getContentEndLoc() const {
175183
for (auto elt : llvm::reverse(getElements())) {
176184
if (auto loc = elt.getEndLoc()) {
177185
return loc;

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
287287
void completeTypeAttrBeginning() override;
288288
void completeOptionalBinding() override;
289289

290-
void doneParsing() override;
290+
void doneParsing(SourceFile *SrcFile) override;
291291

292292
private:
293293
void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
@@ -1552,7 +1552,7 @@ static void undoSingleExpressionReturn(DeclContext *DC) {
15521552
}
15531553
}
15541554

1555-
void CodeCompletionCallbacksImpl::doneParsing() {
1555+
void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
15561556
CompletionContext.CodeCompletionKind = Kind;
15571557

15581558
if (Kind == CompletionKind::None) {

lib/IDE/ConformingMethodList.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class ConformingMethodListCallbacks : public CodeCompletionCallbacks {
4949
void completePostfixExpr(Expr *E, bool hasSpace) override;
5050
// }
5151

52-
void doneParsing() override;
52+
void doneParsing(SourceFile *SrcFile) override;
5353
};
5454

5555
void ConformingMethodListCallbacks::completeDotExpr(CodeCompletionExpr *E,
@@ -64,7 +64,7 @@ void ConformingMethodListCallbacks::completePostfixExpr(Expr *E,
6464
ParsedExpr = E;
6565
}
6666

67-
void ConformingMethodListCallbacks::doneParsing() {
67+
void ConformingMethodListCallbacks::doneParsing(SourceFile *SrcFile) {
6868
if (!ParsedExpr)
6969
return;
7070

0 commit comments

Comments
 (0)