mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Although I don't plan to bring over new assertions wholesale into the current qualification branch, it's entirely possible that various minor changes in main will use the new assertions; having this basic support in the release branch will simplify that. (This is why I'm adding the includes as a separate pass from rewriting the individual assertions)
190 lines
5.8 KiB
C++
190 lines
5.8 KiB
C++
//===--- CodeCompletionStringPrinter.cpp ----------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2022 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/IDE/CodeCompletionStringPrinter.h"
|
|
#include "CodeCompletionResultBuilder.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/Basic/Assertions.h"
|
|
|
|
using namespace swift;
|
|
using namespace swift::ide;
|
|
|
|
using ChunkKind = CodeCompletionString::Chunk::ChunkKind;
|
|
|
|
std::optional<ChunkKind>
|
|
CodeCompletionStringPrinter::getChunkKindForPrintNameContext(
|
|
PrintNameContext context) const {
|
|
switch (context) {
|
|
case PrintNameContext::Keyword:
|
|
if (isCurrentStructureKind(PrintStructureKind::EffectsSpecifiers)) {
|
|
return ChunkKind::EffectsSpecifierKeyword;
|
|
}
|
|
return ChunkKind::Keyword;
|
|
case PrintNameContext::IntroducerKeyword:
|
|
return ChunkKind::DeclIntroducer;
|
|
case PrintNameContext::Attribute:
|
|
return ChunkKind::Attribute;
|
|
case PrintNameContext::FunctionParameterExternal:
|
|
if (isInType()) {
|
|
return std::nullopt;
|
|
}
|
|
return ChunkKind::ParameterDeclExternalName;
|
|
case PrintNameContext::FunctionParameterLocal:
|
|
if (isInType()) {
|
|
return std::nullopt;
|
|
}
|
|
return ChunkKind::ParameterDeclLocalName;
|
|
default:
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
std::optional<ChunkKind>
|
|
CodeCompletionStringPrinter::getChunkKindForStructureKind(
|
|
PrintStructureKind Kind) const {
|
|
switch (Kind) {
|
|
case PrintStructureKind::FunctionParameter:
|
|
if (isInType()) {
|
|
return std::nullopt;
|
|
}
|
|
return ChunkKind::ParameterDeclBegin;
|
|
case PrintStructureKind::DefaultArgumentClause:
|
|
return ChunkKind::DefaultArgumentClauseBegin;
|
|
case PrintStructureKind::DeclGenericParameterClause:
|
|
return ChunkKind::GenericParameterClauseBegin;
|
|
case PrintStructureKind::DeclGenericRequirementClause:
|
|
return ChunkKind::GenericRequirementClauseBegin;
|
|
case PrintStructureKind::EffectsSpecifiers:
|
|
return ChunkKind::EffectsSpecifierClauseBegin;
|
|
case PrintStructureKind::DeclResultTypeClause:
|
|
return ChunkKind::DeclResultTypeClauseBegin;
|
|
case PrintStructureKind::FunctionParameterType:
|
|
return ChunkKind::ParameterDeclTypeBegin;
|
|
default:
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::startNestedGroup(ChunkKind Kind) {
|
|
flush();
|
|
Builder.CurrentNestingLevel++;
|
|
Builder.addSimpleChunk(Kind);
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::endNestedGroup() {
|
|
flush();
|
|
Builder.CurrentNestingLevel--;
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::flush() {
|
|
if (Buffer.empty())
|
|
return;
|
|
Builder.addChunkWithText(CurrChunkKind, Buffer);
|
|
Buffer.clear();
|
|
}
|
|
|
|
/// Start \c AttributeAndModifierListBegin group. This must be called before
|
|
/// any attributes/modifiers printed to the output when printing an override
|
|
/// compleion.
|
|
void CodeCompletionStringPrinter::startPreamble() {
|
|
assert(!InPreamble);
|
|
startNestedGroup(ChunkKind::AttributeAndModifierListBegin);
|
|
InPreamble = true;
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::endPremable() {
|
|
if (!InPreamble)
|
|
return;
|
|
InPreamble = false;
|
|
endNestedGroup();
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printText(StringRef Text) {
|
|
// Detect ': ' and ', ' in parameter clauses.
|
|
// FIXME: Is there a better way?
|
|
if (isCurrentStructureKind(PrintStructureKind::FunctionParameter) &&
|
|
Text == ": ") {
|
|
setNextChunkKind(ChunkKind::ParameterDeclColon);
|
|
} else if (isCurrentStructureKind(
|
|
PrintStructureKind::FunctionParameterList) &&
|
|
Text == ", ") {
|
|
setNextChunkKind(ChunkKind::Comma);
|
|
}
|
|
|
|
if (CurrChunkKind != NextChunkKind) {
|
|
// If the next desired kind is different from the current buffer, flush
|
|
// the current buffer.
|
|
flush();
|
|
CurrChunkKind = NextChunkKind;
|
|
}
|
|
Buffer.append(Text);
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printTypeRef(Type T, const TypeDecl *TD,
|
|
Identifier Name,
|
|
PrintNameContext NameContext) {
|
|
|
|
NextChunkKind = TD->getModuleContext()->isNonUserModule()
|
|
? ChunkKind::TypeIdSystem
|
|
: ChunkKind::TypeIdUser;
|
|
|
|
ASTPrinter::printTypeRef(T, TD, Name, NameContext);
|
|
NextChunkKind = ChunkKind::Text;
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printDeclLoc(const Decl *D) {
|
|
endPremable();
|
|
setNextChunkKind(ChunkKind::BaseName);
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printDeclNameEndLoc(const Decl *D) {
|
|
setNextChunkKind(ChunkKind::Text);
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printNamePre(PrintNameContext context) {
|
|
if (context == PrintNameContext::IntroducerKeyword)
|
|
endPremable();
|
|
if (auto Kind = getChunkKindForPrintNameContext(context))
|
|
setNextChunkKind(*Kind);
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printNamePost(PrintNameContext context) {
|
|
if (getChunkKindForPrintNameContext(context))
|
|
setNextChunkKind(ChunkKind::Text);
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printTypePre(const TypeLoc &TL) {
|
|
++TypeDepth;
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printTypePost(const TypeLoc &TL) {
|
|
assert(TypeDepth > 0);
|
|
--TypeDepth;
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printStructurePre(PrintStructureKind Kind,
|
|
const Decl *D) {
|
|
StructureStack.push_back(Kind);
|
|
|
|
if (auto chunkKind = getChunkKindForStructureKind(Kind))
|
|
startNestedGroup(*chunkKind);
|
|
}
|
|
|
|
void CodeCompletionStringPrinter::printStructurePost(PrintStructureKind Kind,
|
|
const Decl *D) {
|
|
if (getChunkKindForStructureKind(Kind))
|
|
endNestedGroup();
|
|
|
|
assert(Kind == StructureStack.back());
|
|
StructureStack.pop_back();
|
|
}
|