mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CodeCompletion] Avoid typechecking all toplevel decls in the current file
- Use `performParseAndResolveImportsOnly()` to invoke the frontend - Do `bindExtensions()` in `ide::typeCheckContextUntil()` - Typecheck preceding `TopLevelCodeDecl`s only if the compleiton is in a `TopLevelCodeDecl` - Other related tweaks rdar://problem/56636747
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ParameterList.h"
|
||||
#include "swift/AST/Pattern.h"
|
||||
#include "swift/AST/SourceFile.h"
|
||||
#include "swift/AST/Stmt.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/Types.h"
|
||||
@@ -61,10 +62,9 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) {
|
||||
if (auto *patternInit = dyn_cast<PatternBindingInitializer>(DC)) {
|
||||
if (auto *PBD = patternInit->getBinding()) {
|
||||
auto i = patternInit->getBindingIndex();
|
||||
PBD->getPattern(i)->forEachVariable(
|
||||
[](VarDecl *VD) { (void)VD->getInterfaceType(); });
|
||||
if (PBD->getInit(i)) {
|
||||
PBD->getPattern(i)->forEachVariable([](VarDecl *VD) {
|
||||
(void) VD->getInterfaceType();
|
||||
});
|
||||
if (!PBD->isInitializerChecked(i))
|
||||
typeCheckPatternBinding(PBD, i);
|
||||
}
|
||||
@@ -91,15 +91,35 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) {
|
||||
} // anonymous namespace
|
||||
|
||||
void swift::ide::typeCheckContextUntil(DeclContext *DC, SourceLoc Loc) {
|
||||
// The only time we have to explicitly check a TopLevelCodeDecl
|
||||
// is when we're directly inside of one. In this case,
|
||||
// performTypeChecking() did not type check it for us.
|
||||
// Lookup the swift module. This ensures that we record all known
|
||||
// protocols in the AST.
|
||||
(void) DC->getASTContext().getStdlibModule();
|
||||
|
||||
bindExtensions(*DC->getParentSourceFile());
|
||||
|
||||
while (isa<AbstractClosureExpr>(DC))
|
||||
DC = DC->getParent();
|
||||
if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(DC))
|
||||
typeCheckTopLevelCodeDecl(TLCD);
|
||||
else
|
||||
|
||||
if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(DC)) {
|
||||
// Typecheck all 'TopLevelCodeDecl's up to the target one.
|
||||
// In theory, this is not needed, but it fails to resolve the type of
|
||||
// 'guard'ed variable. e.g.
|
||||
//
|
||||
// guard value = something() else { fatalError() }
|
||||
// <complete>
|
||||
// Here, 'value' is '<error type>' unless we explicitly typecheck the
|
||||
// 'guard' statement.
|
||||
SourceFile *SF = DC->getParentSourceFile();
|
||||
for (auto *D : SF->Decls) {
|
||||
if (auto Code = dyn_cast<TopLevelCodeDecl>(D)) {
|
||||
typeCheckTopLevelCodeDecl(Code);
|
||||
if (Code == TLCD)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
typeCheckContextImpl(DC, Loc);
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Reference in New Issue
Block a user