blob: f8098fbaf83903ad5efdb5458be502b241a444c5 [file] [log] [blame]
//===--- CodeCompletion.h - -------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SOURCEKIT_LIB_SWIFTLANG_CODECOMPLETION_H
#define LLVM_SOURCEKIT_LIB_SWIFTLANG_CODECOMPLETION_H
#include "SourceKit/Core/LLVM.h"
#include "swift/IDE/CodeCompletion.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
namespace SourceKit {
namespace CodeCompletion {
using swift::ide::CodeCompletionDeclKind;
using swift::ide::CodeCompletionKeywordKind;
using swift::ide::CodeCompletionLiteralKind;
using swift::ide::SemanticContextKind;
using swift::ide::CodeCompletionString;
using SwiftResult = swift::ide::CodeCompletionResult;
using swift::ide::CompletionKind;
struct Group;
class CodeCompletionOrganizer;
class CompletionBuilder;
/// A representation of the 'popularity' of a code completion result.
struct PopularityFactor {
/// Raw popularity score in the range [-1, 1], where higher values are more
/// popular and 0.0 indicates an unknown popularity.
double rawValue = 0.0;
bool isPopular() const { return rawValue > 0.0; }
bool isUnpopular() const { return rawValue < 0.0; }
PopularityFactor() = default;
explicit PopularityFactor(double value) : rawValue(value) {}
};
struct NameStyle {
enum WordDelimiter : uint8_t {
Unknown,
Lowercase, // lowercase
Uppercase, // UPPERCASE
UpperCamelCase, // UpperCamelCase
LowerCamelCase, // lowerCamelCase
LowercaseWithUnderscores, // lowercase_with_underscores
UppercaseWithUnderscores, // UPPERCASE_WITH_UNDERSCORES
};
WordDelimiter wordDelimiter = Unknown;
uint8_t leadingUnderscores : 2;
uint8_t trailingUnderscores : 2;
explicit NameStyle(StringRef name);
bool possiblyLowerCamelCase() const {
return wordDelimiter == Lowercase || wordDelimiter == LowerCamelCase;
}
bool possiblyUpperCamelCase() const {
return wordDelimiter == Uppercase || wordDelimiter == UpperCamelCase;
}
};
/// Code completion result type for SourceKit::SwiftLangSupport.
///
/// Extends a \c swift::ide::CodeCompletionResult with extra fields that are
/// filled in by SourceKit. Generally stored in an \c CompletionSink.
class Completion : public SwiftResult {
void *opaqueCustomKind = nullptr;
Optional<uint8_t> moduleImportDepth;
PopularityFactor popularityFactor;
StringRef name;
StringRef description;
friend class CompletionBuilder;
public:
static constexpr unsigned numSemanticContexts = 8;
static constexpr unsigned maxModuleImportDepth = 10;
/// Wraps \p base with an \c Completion. The \p name and \p description
/// should outlive the result, generally by being stored in the same
/// \c CompletionSink.
Completion(SwiftResult base, StringRef name, StringRef description)
: SwiftResult(base), name(name), description(description) {}
bool hasCustomKind() const { return opaqueCustomKind; }
void *getCustomKind() const { return opaqueCustomKind; }
StringRef getName() const { return name; }
StringRef getDescription() const { return description; }
Optional<uint8_t> getModuleImportDepth() const { return moduleImportDepth; }
/// A popularity factory in the range [-1, 1]. The higher the value, the more
/// 'popular' this result is. 0 indicates unknown.
PopularityFactor getPopularityFactor() const { return popularityFactor; }
};
/// Storage sink for \c Completion objects.
///
/// In addition to allocating the results themselves, uses \c swiftSink to keep
/// the storage for the underlying swift results alive.
struct CompletionSink {
swift::ide::CodeCompletionResultSink swiftSink;
llvm::BumpPtrAllocator allocator;
/// Adds references to a swift sink's allocators to keep its storage alive.
void adoptSwiftSink(swift::ide::CodeCompletionResultSink &sink) {
swiftSink.ForeignAllocators.insert(swiftSink.ForeignAllocators.end(),
sink.ForeignAllocators.begin(),
sink.ForeignAllocators.end());
swiftSink.ForeignAllocators.push_back(sink.Allocator);
}
};
class CompletionBuilder {
CompletionSink &sink;
SwiftResult &current;
bool modified = false;
Completion::ExpectedTypeRelation typeRelation;
SemanticContextKind semanticContext;
CodeCompletionString *completionString;
llvm::SmallVector<char, 64> originalName;
void *customKind = nullptr;
Optional<uint8_t> moduleImportDepth;
PopularityFactor popularityFactor;
public:
CompletionBuilder(CompletionSink &sink, SwiftResult &base);
void setCustomKind(void *opaqueCustomKind) { customKind = opaqueCustomKind; }
void setModuleImportDepth(Optional<uint8_t> value) {
assert(!value || *value <= Completion::maxModuleImportDepth);
moduleImportDepth = value;
}
void setExpectedTypeRelation(Completion::ExpectedTypeRelation Relation) {
modified = true;
typeRelation = Relation;
}
void setSemanticContext(SemanticContextKind kind) {
modified = true;
semanticContext = kind;
}
void setPopularityFactor(PopularityFactor val) { popularityFactor = val; }
void setPrefix(CodeCompletionString *prefix);
StringRef getOriginalName() const {
return StringRef(originalName.begin(), originalName.size());
}
Completion *finish();
};
/// Immutable view of code completion results.
///
/// Provides a possibly filtered view of code completion results
/// (\c Completion) organized into groups. Clients walk the tree using
/// CodeCompletionView::Walker. The \c Completion objects are not owned
/// by the view and must outlive it.
class CodeCompletionView {
const Group *rootGroup = nullptr; ///< Owned by the view.
friend class CodeCompletionOrganizer;
friend class LimitedResultView;
CodeCompletionView(const CodeCompletionView &) = delete;
void operator=(const CodeCompletionView &) = delete;
public:
CodeCompletionView() = default;
CodeCompletionView(CodeCompletionView &&) = default;
virtual ~CodeCompletionView();
struct Walker;
virtual bool walk(Walker &walker) const;
};
/// Interface implemented by clients of \c CodeCompletionView.
struct CodeCompletionView::Walker {
virtual ~Walker() {}
virtual bool handleResult(Completion *result) = 0;
virtual void startGroup(StringRef name) = 0;
virtual void endGroup() = 0;
};
using CodeCompletionViewRef = std::shared_ptr<const CodeCompletionView>;
class LimitedResultView : public CodeCompletionView {
const CodeCompletionView &baseView;
mutable unsigned start;
unsigned maxResults;
public:
LimitedResultView(const CodeCompletionView &baseView, unsigned start,
unsigned maxResults)
: baseView(baseView), start(start), maxResults(maxResults) {}
unsigned getNextOffset() const;
bool walk(Walker &walker) const override;
};
struct FilterRules {
bool hideAll = false;
bool hideAllValueLiterals = false;
llvm::SmallDenseMap<CodeCompletionLiteralKind, bool, 8> hideValueLiteral;
bool hideAllKeywords = false;
llvm::DenseMap<CodeCompletionKeywordKind, bool> hideKeyword;
bool hideCustomCompletions = false;
// FIXME: hide individual custom completions
llvm::StringMap<bool> hideModule;
llvm::StringMap<bool> hideByFilterName;
llvm::StringMap<bool> hideByDescription;
bool hideCompletion(Completion *completion) const;
bool hideCompletion(SwiftResult *completion, StringRef name,
StringRef description, void *customKind = nullptr) const;
bool hideFilterName(StringRef name) const;
};
} // end namespace CodeCompletion
} // end namespace SourceKit
#endif // LLVM_SOURCEKIT_LIB_SWIFTLANG_CODECOMPLETION_H