mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CodeCompletion] Add rudimentary support for configuring allowable completions
On a per-request basis. Allows hiding/showing at multiple granularities * everything * module * API by name * keywords (by uid or all of them) * literals (by uid or all of them) With more specific rules overriding less specific ones (so you can hide everything and then selectively show certain API for example). rdar://24170060
This commit is contained in:
@@ -534,6 +534,45 @@ bool SwiftToSourceKitCompletionAdapter::handleResult(
|
||||
return Consumer.handleResult(Info);
|
||||
}
|
||||
|
||||
static CodeCompletionLiteralKind
|
||||
getCodeCompletionLiteralKindForUID(UIdent uid) {
|
||||
if (uid == KindLiteralArray) {
|
||||
return CodeCompletionLiteralKind::ArrayLiteral;
|
||||
} else if (uid == KindLiteralBoolean) {
|
||||
return CodeCompletionLiteralKind::BooleanLiteral;
|
||||
} else if (uid == KindLiteralColor) {
|
||||
return CodeCompletionLiteralKind::ColorLiteral;
|
||||
} else if (uid == KindLiteralDictionary) {
|
||||
return CodeCompletionLiteralKind::DictionaryLiteral;
|
||||
} else if (uid == KindLiteralFloat) {
|
||||
return CodeCompletionLiteralKind::FloatLiteral;
|
||||
} else if (uid == KindLiteralInteger) {
|
||||
return CodeCompletionLiteralKind::IntegerLiteral;
|
||||
} else if (uid == KindLiteralNil) {
|
||||
return CodeCompletionLiteralKind::NilLiteral;
|
||||
} else if (uid == KindLiteralString) {
|
||||
return CodeCompletionLiteralKind::StringLiteral;
|
||||
} else if (uid == KindLiteralTuple) {
|
||||
return CodeCompletionLiteralKind::Tuple;
|
||||
} else {
|
||||
llvm_unreachable("unexpected literal kind");
|
||||
}
|
||||
}
|
||||
|
||||
static CodeCompletionKeywordKind
|
||||
getCodeCompletionKeywordKindForUID(UIdent uid) {
|
||||
#define SIL_KEYWORD(kw)
|
||||
#define KEYWORD(kw) \
|
||||
static UIdent Keyword##kw##UID("source.lang.swift.keyword." #kw); \
|
||||
if (uid == Keyword##kw##UID) { \
|
||||
return CodeCompletionKeywordKind::kw_##kw; \
|
||||
}
|
||||
#include "swift/Parse/Tokens.def"
|
||||
|
||||
// FIXME: should warn about unexpected keyword kind.
|
||||
return CodeCompletionKeywordKind::None;
|
||||
}
|
||||
|
||||
using ChunkKind = CodeCompletionString::Chunk::ChunkKind;
|
||||
|
||||
/// Provide the text for the call parameter, including constructing a typed
|
||||
@@ -658,6 +697,11 @@ CompletionKind CodeCompletion::SessionCache::getCompletionKind() {
|
||||
llvm::sys::ScopedLock L(mtx);
|
||||
return completionKind;
|
||||
}
|
||||
const CodeCompletion::FilterRules &
|
||||
CodeCompletion::SessionCache::getFilterRules() {
|
||||
llvm::sys::ScopedLock L(mtx);
|
||||
return filterRules;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CodeCompletion::SessionCacheMap
|
||||
@@ -760,6 +804,48 @@ static void translateCodeCompletionOptions(OptionsDictionary &from,
|
||||
from.valueForOption(KeyHideByName, to.hideByNameStyle);
|
||||
}
|
||||
|
||||
static void translateFilterRules(ArrayRef<FilterRule> rawFilterRules,
|
||||
CodeCompletion::FilterRules &filterRules) {
|
||||
for (auto &rule : rawFilterRules) {
|
||||
switch (rule.kind) {
|
||||
case FilterRule::Everything:
|
||||
filterRules.hideAll = rule.hide;
|
||||
break;
|
||||
case FilterRule::Identifier:
|
||||
for (auto name : rule.names) {
|
||||
filterRules.hideByName[name] = rule.hide;
|
||||
}
|
||||
break;
|
||||
case FilterRule::Module:
|
||||
for (auto name : rule.names) {
|
||||
filterRules.hideModule[name] = rule.hide;
|
||||
}
|
||||
break;
|
||||
case FilterRule::Keyword:
|
||||
if (rule.uids.empty())
|
||||
filterRules.hideAllKeywords = rule.hide;
|
||||
for (auto uid : rule.uids) {
|
||||
auto kind = getCodeCompletionKeywordKindForUID(uid);
|
||||
filterRules.hideKeyword[kind] = rule.hide;
|
||||
}
|
||||
break;
|
||||
case FilterRule::Literal:
|
||||
if (rule.uids.empty())
|
||||
filterRules.hideAllValueLiterals = rule.hide;
|
||||
for (auto uid : rule.uids) {
|
||||
auto kind = getCodeCompletionLiteralKindForUID(uid);
|
||||
filterRules.hideValueLiteral[kind] = rule.hide;
|
||||
}
|
||||
break;
|
||||
case FilterRule::CustomCompletion:
|
||||
if (rule.uids.empty())
|
||||
filterRules.hideCustomCompletions = rule.hide;
|
||||
// FIXME: hide individual custom completions
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkInnerResult(CodeCompletionResult *result, bool &hasDot,
|
||||
bool &hasQDot, bool &hasInit) {
|
||||
auto chunks = result->getCompletionString()->getChunks();
|
||||
@@ -849,7 +935,8 @@ static void transformAndForwardResults(
|
||||
|
||||
if (!hasEarlyInnerResults) {
|
||||
organizer.addCompletionsWithFilter(session->getSortedCompletions(),
|
||||
filterText, exactMatch);
|
||||
filterText, session->getFilterRules(),
|
||||
exactMatch);
|
||||
}
|
||||
|
||||
if (hasEarlyInnerResults &&
|
||||
@@ -870,7 +957,8 @@ static void transformAndForwardResults(
|
||||
innerResults.insert(innerResults.begin(), buildQDot());
|
||||
}
|
||||
|
||||
organizer.addCompletionsWithFilter(innerResults, filterText, exactMatch);
|
||||
organizer.addCompletionsWithFilter(innerResults, filterText,
|
||||
session->getFilterRules(), exactMatch);
|
||||
}
|
||||
|
||||
organizer.groupAndSort(options);
|
||||
@@ -925,7 +1013,8 @@ static void transformAndForwardResults(
|
||||
|
||||
// Add the inner results (and don't filter them).
|
||||
exactMatch = nullptr; // No longer needed.
|
||||
organizer.addCompletionsWithFilter(innerResults, filterText, exactMatch);
|
||||
organizer.addCompletionsWithFilter(innerResults, filterText,
|
||||
session->getFilterRules(), exactMatch);
|
||||
|
||||
CodeCompletion::Options noGroupOpts = options;
|
||||
noGroupOpts.groupStems = false;
|
||||
@@ -944,12 +1033,10 @@ static void transformAndForwardResults(
|
||||
consumer.setNextRequestStart(limitedResults.getNextOffset());
|
||||
}
|
||||
|
||||
void SwiftLangSupport::codeCompleteOpen(StringRef name,
|
||||
llvm::MemoryBuffer *inputBuf,
|
||||
unsigned offset,
|
||||
OptionsDictionary *options,
|
||||
GroupedCodeCompletionConsumer &consumer,
|
||||
ArrayRef<const char *> args) {
|
||||
void SwiftLangSupport::codeCompleteOpen(
|
||||
StringRef name, llvm::MemoryBuffer *inputBuf, unsigned offset,
|
||||
OptionsDictionary *options, ArrayRef<FilterRule> rawFilterRules,
|
||||
GroupedCodeCompletionConsumer &consumer, ArrayRef<const char *> args) {
|
||||
StringRef filterText;
|
||||
unsigned resultOffset = 0;
|
||||
unsigned maxResults = 0;
|
||||
@@ -958,6 +1045,9 @@ void SwiftLangSupport::codeCompleteOpen(StringRef name,
|
||||
translateCodeCompletionOptions(*options, CCOpts, filterText, resultOffset,
|
||||
maxResults);
|
||||
|
||||
CodeCompletion::FilterRules filterRules;
|
||||
translateFilterRules(rawFilterRules, filterRules);
|
||||
|
||||
// Set up the code completion consumer to pass results to organizer.
|
||||
CodeCompletion::CompletionSink sink;
|
||||
std::vector<Completion *> completions;
|
||||
@@ -1005,9 +1095,9 @@ void SwiftLangSupport::codeCompleteOpen(StringRef name,
|
||||
auto bufferCopy = llvm::MemoryBuffer::getMemBufferCopy(
|
||||
inputBuf->getBuffer(), inputBuf->getBufferIdentifier());
|
||||
std::vector<std::string> argsCopy(extendedArgs.begin(), extendedArgs.end());
|
||||
SessionCacheRef session{
|
||||
new SessionCache(std::move(sink), std::move(bufferCopy),
|
||||
std::move(argsCopy), completionKind)};
|
||||
SessionCacheRef session{new SessionCache(
|
||||
std::move(sink), std::move(bufferCopy), std::move(argsCopy),
|
||||
completionKind, std::move(filterRules))};
|
||||
session->setSortedCompletions(std::move(completions));
|
||||
|
||||
if (!CCSessions.set(name, offset, session)) {
|
||||
|
||||
Reference in New Issue
Block a user