mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #23587 from benlangmuir/cc-omit-return
[code-completion] Add type context for single-expression function bodies
This commit is contained in:
@@ -103,7 +103,7 @@ std::vector<Completion *> SourceKit::CodeCompletion::extendCompletions(
|
||||
if (result->getSemanticContext() == SemanticContextKind::OtherModule) {
|
||||
builder.setModuleImportDepth(depth.lookup(result->getModuleName()));
|
||||
|
||||
if (info.completionContext->HasExpectedTypeRelation &&
|
||||
if (info.completionContext->typeContextKind == TypeContextKind::Required &&
|
||||
result->getKind() == Completion::Declaration) {
|
||||
// FIXME: because other-module results are cached, they will not be
|
||||
// given a type-relation of invalid. As a hack, we look at the text of
|
||||
@@ -213,13 +213,13 @@ bool SourceKit::CodeCompletion::addCustomCompletions(
|
||||
class CodeCompletionOrganizer::Impl {
|
||||
std::unique_ptr<Group> rootGroup;
|
||||
CompletionKind completionKind;
|
||||
bool completionHasExpectedTypes;
|
||||
TypeContextKind typeContextKind;
|
||||
|
||||
void groupStemsRecursive(Group *group, bool recurseIntoNewGroups,
|
||||
StringRef(getStem)(StringRef));
|
||||
|
||||
public:
|
||||
Impl(CompletionKind kind, bool hasExpectedTypes);
|
||||
Impl(CompletionKind kind, TypeContextKind typeContextKind);
|
||||
|
||||
void addCompletionsWithFilter(ArrayRef<Completion *> completions,
|
||||
StringRef filterText, Options options,
|
||||
@@ -276,8 +276,8 @@ public:
|
||||
|
||||
CodeCompletionOrganizer::CodeCompletionOrganizer(const Options &options,
|
||||
CompletionKind kind,
|
||||
bool hasExpectedTypes)
|
||||
: impl(*new Impl(kind, hasExpectedTypes)), options(options) {}
|
||||
TypeContextKind typeContextKind)
|
||||
: impl(*new Impl(kind, typeContextKind)), options(options) {}
|
||||
CodeCompletionOrganizer::~CodeCompletionOrganizer() { delete &impl; }
|
||||
|
||||
void CodeCompletionOrganizer::preSortCompletions(
|
||||
@@ -413,8 +413,8 @@ static std::unique_ptr<Result> make_result(Completion *result) {
|
||||
// CodeCompletionOrganizer::Impl implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
CodeCompletionOrganizer::Impl::Impl(CompletionKind kind, bool hasExpectedTypes)
|
||||
: completionKind(kind), completionHasExpectedTypes(hasExpectedTypes) {
|
||||
CodeCompletionOrganizer::Impl::Impl(CompletionKind kind, TypeContextKind typeContextKind)
|
||||
: completionKind(kind), typeContextKind(typeContextKind) {
|
||||
assert(!rootGroup && "initialized twice");
|
||||
rootGroup = make_group("");
|
||||
}
|
||||
@@ -574,7 +574,7 @@ void CodeCompletionOrganizer::Impl::addCompletionsWithFilter(
|
||||
if (completion->getExpectedTypeRelation() >= Completion::Convertible ||
|
||||
(completion->getKind() == Completion::Literal &&
|
||||
completionKind != CompletionKind::StmtOrExpr &&
|
||||
!completionHasExpectedTypes))
|
||||
typeContextKind < TypeContextKind::Required))
|
||||
break;
|
||||
|
||||
if (completion->getKind() == Completion::Keyword &&
|
||||
@@ -604,7 +604,7 @@ void CodeCompletionOrganizer::Impl::addCompletionsWithFilter(
|
||||
// Hide literals other than the ones that are also keywords if they don't
|
||||
// match the expected types.
|
||||
if (completion->getKind() == Completion::Literal &&
|
||||
completionHasExpectedTypes &&
|
||||
typeContextKind == TypeContextKind::Required &&
|
||||
completion->getExpectedTypeRelation() < Completion::Convertible &&
|
||||
completion->getLiteralKind() !=
|
||||
CodeCompletionLiteralKind::BooleanLiteral &&
|
||||
@@ -720,7 +720,7 @@ enum class ResultBucket {
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static ResultBucket getResultBucket(Item &item, bool hasExpectedTypes,
|
||||
static ResultBucket getResultBucket(Item &item, bool hasRequiredTypes,
|
||||
bool skipMetaGroups = false) {
|
||||
if (item.isExactMatch && !skipMetaGroups)
|
||||
return ResultBucket::ExactMatch;
|
||||
@@ -747,7 +747,7 @@ static ResultBucket getResultBucket(Item &item, bool hasExpectedTypes,
|
||||
case Completion::Literal:
|
||||
if (matchesType) {
|
||||
return ResultBucket::LiteralTypeMatch;
|
||||
} else if (!hasExpectedTypes) {
|
||||
} else if (!hasRequiredTypes) {
|
||||
return ResultBucket::Literal;
|
||||
} else {
|
||||
// When we have type context, we still show literals that are keywords,
|
||||
@@ -912,19 +912,19 @@ static bool isTopNonLiteralResult(Item &item, ResultBucket literalBucket) {
|
||||
}
|
||||
|
||||
static void sortTopN(const Options &options, Group *group,
|
||||
bool hasExpectedTypes) {
|
||||
bool hasRequiredTypes) {
|
||||
|
||||
auto &contents = group->contents;
|
||||
if (contents.empty() || options.showTopNonLiteralResults == 0)
|
||||
return;
|
||||
|
||||
auto best = getResultBucket(*contents[0], hasExpectedTypes);
|
||||
auto best = getResultBucket(*contents[0], hasRequiredTypes);
|
||||
if (best == ResultBucket::LiteralTypeMatch || best == ResultBucket::Literal) {
|
||||
|
||||
unsigned beginNewIndex = 0;
|
||||
unsigned endNewIndex = 0;
|
||||
for (unsigned i = 1; i < contents.size(); ++i) {
|
||||
auto bucket = getResultBucket(*contents[i], hasExpectedTypes);
|
||||
auto bucket = getResultBucket(*contents[i], hasRequiredTypes);
|
||||
if (bucket < best) {
|
||||
// This algorithm assumes we don't have both literal and
|
||||
// literal-type-match at the start of the list.
|
||||
@@ -969,13 +969,13 @@ static void sortTopN(const Options &options, Group *group,
|
||||
}
|
||||
|
||||
static void sortRecursive(const Options &options, Group *group,
|
||||
bool hasExpectedTypes) {
|
||||
bool hasRequiredTypes) {
|
||||
// Sort all of the subgroups first, and fill in the bucket for each result.
|
||||
auto &contents = group->contents;
|
||||
double best = -1.0;
|
||||
for (auto &item : contents) {
|
||||
if (auto *g = dyn_cast<Group>(item.get())) {
|
||||
sortRecursive(options, g, hasExpectedTypes);
|
||||
sortRecursive(options, g, hasRequiredTypes);
|
||||
} else {
|
||||
Result *r = cast<Result>(item.get());
|
||||
item->finalScore = combinedScore(options, item->matchScore, r->value);
|
||||
@@ -1001,8 +1001,8 @@ static void sortRecursive(const Options &options, Group *group,
|
||||
Item &a = *a_;
|
||||
Item &b = *b_;
|
||||
|
||||
auto bucketA = getResultBucket(a, hasExpectedTypes);
|
||||
auto bucketB = getResultBucket(b, hasExpectedTypes);
|
||||
auto bucketA = getResultBucket(a, hasRequiredTypes);
|
||||
auto bucketB = getResultBucket(b, hasRequiredTypes);
|
||||
if (bucketA < bucketB)
|
||||
return false;
|
||||
else if (bucketB < bucketA)
|
||||
@@ -1013,8 +1013,8 @@ static void sortRecursive(const Options &options, Group *group,
|
||||
if (bucketA == ResultBucket::ExactMatch ||
|
||||
bucketA == ResultBucket::ExpressionSpecific ||
|
||||
bucketA == ResultBucket::NotRecommended) {
|
||||
bucketA = getResultBucket(a, hasExpectedTypes, /*skipMetaGroups*/ true);
|
||||
bucketB = getResultBucket(b, hasExpectedTypes, /*skipMetaGroups*/ true);
|
||||
bucketA = getResultBucket(a, hasRequiredTypes, /*skipMetaGroups*/ true);
|
||||
bucketB = getResultBucket(b, hasRequiredTypes, /*skipMetaGroups*/ true);
|
||||
if (bucketA < bucketB)
|
||||
return false;
|
||||
else if (bucketB < bucketA)
|
||||
@@ -1049,9 +1049,10 @@ static void sortRecursive(const Options &options, Group *group,
|
||||
}
|
||||
|
||||
void CodeCompletionOrganizer::Impl::sort(Options options) {
|
||||
sortRecursive(options, rootGroup.get(), completionHasExpectedTypes);
|
||||
bool hasRequiredTypes = typeContextKind == TypeContextKind::Required;
|
||||
sortRecursive(options, rootGroup.get(), hasRequiredTypes);
|
||||
if (options.showTopNonLiteralResults != 0)
|
||||
sortTopN(options, rootGroup.get(), completionHasExpectedTypes);
|
||||
sortTopN(options, rootGroup.get(), hasRequiredTypes);
|
||||
}
|
||||
|
||||
void CodeCompletionOrganizer::Impl::groupStemsRecursive(
|
||||
|
||||
Reference in New Issue
Block a user