swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.58k stars 10.36k forks source link

[SR-2015] Code completion shows unrelated enum cases in definitions of lazy vars #44625

Open swift-ci opened 8 years ago

swift-ci commented 8 years ago
Previous ID SR-2015
Radar None
Original Reporter mattrajca (JIRA User)
Type Bug

Attachment: Download

Environment Xcode 7.3.1 GM Xcode 8 seed 2 OS X 10.11.5 GM
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 1 | |Component/s | CodeCompletion | |Labels | Bug | |Assignee | @benlangmuir | |Priority | Medium | md5: 5cf1d6b5d8fe365fc63fc9fb6315a7a5

Issue Description:

Consider the code snippet below (also attached a Swift Playground EnumCases.playground.zip ).


import UIKit

class Test {
    lazy var dateFormatter: NSDateFormatter = {
        let dateFormatter = NSDateFormatter()
        dateFormatter.timeStyle = .
        //                         ^bring up code completions here
    }()
}

When completions are requested at the indicated position, enum cases for NSDateIntervalFormatterStyle are erroneously suggested since the type of timeStyle is NSDateFormatterStyle.

Screenshot:

benlangmuir commented 8 years ago

There seem to be two issues here.
1) We're failing to find the correct parent expression whenever it's inside a closure expression. I have a fix for this (not pushed yet).
2) We're failing to setup a type variable for the unresolved member expression. I'm looking into why.

benlangmuir commented 8 years ago

The reason for (2) is that typeCheckContext doesn't type check inside closure bodies that are in a variable initializer and without type checking the containing expression we have a SequenceExpr instead of an AssignExpr, and CSGen doesn't handle SequenceExpr. We could locally fix typeCheckUnresolvedExpression to fold the sequence, but a more wholistic fix to typeCheckContext for handling closures might solve some other issues with closures in initializers.

Note for posterity: the fix for (1) is below, but this won't pass the existing tests until we fix (2).

diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index f16c63d..a2ccc71 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -5144,7 +5162,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
     Lookup.setHaveDot(SourceLoc());
     SmallVector<Type, 1> PossibleTypes;
     ExprParentFinder Walker(UnresolvedExpr, [&](ASTNode Node) {
-      return Node.is<Expr *>();
+      return Node.is<Expr *>() && !isa<ClosureExpr>(Node.get<Expr *>());
     });
     CurDeclContext->walkContext(Walker);
     bool Success = false;