| //===--- 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 ¤t; |
| 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 |