Files
swift-mirror/lib/IDE/SwiftSourceDocInfo.cpp
Ben Barham ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00

260 lines
7.8 KiB
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
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/NameLookup.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/Utils.h"
#include "swift/Markup/XMLUtils.h"
#include "swift/Subsystems.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/MemoryBuffer.h"
#include <numeric>
using namespace swift;
using namespace swift::ide;
std::optional<std::pair<unsigned, unsigned>>
swift::ide::parseLineCol(StringRef LineCol) {
unsigned Line, Col;
size_t ColonIdx = LineCol.find(':');
if (ColonIdx == StringRef::npos) {
llvm::errs() << "wrong pos format, it should be '<line>:<column>'\n";
return std::nullopt;
}
if (LineCol.substr(0, ColonIdx).getAsInteger(10, Line)) {
llvm::errs() << "wrong pos format, it should be '<line>:<column>'\n";
return std::nullopt;
}
if (LineCol.substr(ColonIdx+1).getAsInteger(10, Col)) {
llvm::errs() << "wrong pos format, it should be '<line>:<column>'\n";
return std::nullopt;
}
if (Line == 0 || Col == 0) {
llvm::errs() << "wrong pos format, line/col should start from 1\n";
return std::nullopt;
}
return std::make_pair(Line, Col);
}
void XMLEscapingPrinter::printText(StringRef Text) {
swift::markup::appendWithXMLEscaping(OS, Text);
}
void XMLEscapingPrinter::printXML(StringRef Text) {
OS << Text;
}
void ResolvedRangeInfo::print(llvm::raw_ostream &OS) const {
OS << "<Kind>";
switch (Kind) {
case RangeKind::SingleExpression: OS << "SingleExpression"; break;
case RangeKind::SingleDecl: OS << "SingleDecl"; break;
case RangeKind::MultiTypeMemberDecl: OS << "MultiTypeMemberDecl"; break;
case RangeKind::MultiStatement: OS << "MultiStatement"; break;
case RangeKind::PartOfExpression: OS << "PartOfExpression"; break;
case RangeKind::SingleStatement: OS << "SingleStatement"; break;
case RangeKind::Invalid: OS << "Invalid"; break;
}
OS << "</Kind>\n";
OS << "<Content>" << ContentRange.str() << "</Content>\n";
if (auto Ty = getType()) {
OS << "<Type>";
Ty->print(OS);
OS << "</Type>";
switch(exit()) {
case ExitState::Positive: OS << "<Exit>true</Exit>"; break;
case ExitState::Unsure: OS << "<Exit>unsure</Exit>"; break;
case ExitState::Negative: OS << "<Exit>false</Exit>"; break;
}
OS << "\n";
}
if (RangeContext) {
OS << "<Context>";
printContext(OS, RangeContext);
OS << "</Context>\n";
}
if (CommonExprParent) {
OS << "<Parent>";
OS << Expr::getKindName(CommonExprParent->getKind());
OS << "</Parent>\n";
}
if (!HasSingleEntry) {
OS << "<Entry>Multi</Entry>\n";
}
if (UnhandledEffects.contains(EffectKind::Throws)) {
OS << "<Error>Throwing</Error>\n";
}
if (UnhandledEffects.contains(EffectKind::Async)) {
OS << "<Effect>Async</Effect>\n";
}
if (Orphan != OrphanKind::None) {
OS << "<Orphan>";
switch (Orphan) {
case OrphanKind::Continue:
OS << "Continue";
break;
case OrphanKind::Break:
OS << "Break";
break;
case OrphanKind::None:
llvm_unreachable("cannot enter here.");
}
OS << "</Orphan>";
}
for (auto &VD : DeclaredDecls) {
OS << "<Declared>" << VD.VD->getBaseName() << "</Declared>";
OS << "<OutscopeReference>";
if (VD.ReferredAfterRange)
OS << "true";
else
OS << "false";
OS << "</OutscopeReference>\n";
}
for (auto &RD : ReferencedDecls) {
OS << "<Referenced>" << RD.VD->getBaseName() << "</Referenced>";
OS << "<Type>";
RD.Ty->print(OS);
OS << "</Type>\n";
}
OS << "<ASTNodes>" << ContainedNodes.size() << "</ASTNodes>\n";
OS << "<end>\n";
}
CharSourceRange ResolvedRangeInfo::
calculateContentRange(ArrayRef<Token> Tokens) {
if (Tokens.empty())
return CharSourceRange();
auto StartTok = Tokens.front();
auto EndTok = Tokens.back();
auto StartLoc = StartTok.hasComment() ?
StartTok.getCommentStart() : StartTok.getLoc();
auto EndLoc = EndTok.getRange().getEnd();
auto Length = static_cast<const char *>(EndLoc.getOpaquePointerValue()) -
static_cast<const char *>(StartLoc.getOpaquePointerValue());
return CharSourceRange(StartLoc, Length);
}
bool DeclaredDecl::operator==(const DeclaredDecl& Other) const {
return VD == Other.VD;
}
ReturnInfo::
ReturnInfo(ASTContext &Ctx, ArrayRef<ReturnInfo> Branches):
ReturnType(Ctx.TheErrorType.getPointer()), Exit(ExitState::Unsure) {
std::set<TypeBase*> AllTypes;
std::set<ExitState> AllExitStates;
for (auto I : Branches) {
AllTypes.insert(I.ReturnType);
AllExitStates.insert(I.Exit);
}
if (AllTypes.size() == 1) {
ReturnType = *AllTypes.begin();
}
if (AllExitStates.size() == 1) {
Exit = *AllExitStates.begin();
}
}
CharSourceRange CallArgInfo::getEntireCharRange(const SourceManager &SM) const {
return CharSourceRange(SM, LabelRange.getStart(),
Lexer::getLocForEndOfToken(SM, ArgExp->getEndLoc()));
}
static Expr* getSingleNonImplicitChild(Expr *Parent) {
// If this expr is non-implicit, we are done.
if (!Parent->isImplicit())
return Parent;
// Collect all immediate children.
llvm::SmallVector<Expr*, 4> Children;
Parent->forEachImmediateChildExpr([&](Expr *E) {
Children.push_back(E);
return E;
});
// If more than one children are found, we are not sure the non-implicit node.
if (Children.size() != 1)
return Parent;
// Dig deeper if necessary.
return getSingleNonImplicitChild(Children[0]);
}
std::vector<CallArgInfo> swift::ide::
getCallArgInfo(SourceManager &SM, ArgumentList *Args, LabelRangeEndAt EndKind) {
std::vector<CallArgInfo> InfoVec;
auto *OriginalArgs = Args->getOriginalArgs();
for (auto ElemIndex : indices(*OriginalArgs)) {
auto *Elem = OriginalArgs->getExpr(ElemIndex);
SourceLoc LabelStart(Elem->getStartLoc());
SourceLoc LabelEnd(LabelStart);
bool IsTrailingClosure = OriginalArgs->isTrailingClosureIndex(ElemIndex);
auto NameLoc = OriginalArgs->getLabelLoc(ElemIndex);
if (NameLoc.isValid()) {
LabelStart = NameLoc;
if (EndKind == LabelRangeEndAt::LabelNameOnly || IsTrailingClosure) {
LabelEnd = Lexer::getLocForEndOfToken(SM, NameLoc);
}
}
InfoVec.push_back({getSingleNonImplicitChild(Elem),
CharSourceRange(SM, LabelStart, LabelEnd),
IsTrailingClosure});
}
return InfoVec;
}
std::pair<std::vector<CharSourceRange>, std::optional<unsigned>>
swift::ide::getCallArgLabelRanges(SourceManager &SM, ArgumentList *Args,
LabelRangeEndAt EndKind) {
std::vector<CharSourceRange> Ranges;
auto InfoVec = getCallArgInfo(SM, Args, EndKind);
std::optional<unsigned> FirstTrailing;
auto I = std::find_if(InfoVec.begin(), InfoVec.end(), [](CallArgInfo &Info) {
return Info.IsTrailingClosure;
});
if (I != InfoVec.end())
FirstTrailing = std::distance(InfoVec.begin(), I);
llvm::transform(InfoVec, std::back_inserter(Ranges),
[](CallArgInfo &Info) { return Info.LabelRange; });
return {Ranges, FirstTrailing};
}