blob: 0c53cd3d3738a7d0b742cb9f06b2e2553e5ac2ef [file] [log] [blame]
//===--- Syntax.cpp - Swift Syntax Implementation -------------------------===//
//
// 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/Syntax/Syntax.h"
#include "swift/Syntax/SyntaxData.h"
#include "swift/Syntax/SyntaxVisitor.h"
using namespace swift;
using namespace swift::syntax;
RC<RawSyntax> Syntax::getRaw() const {
return Data->getRaw();
}
SyntaxKind Syntax::getKind() const {
return getRaw()->getKind();
}
void Syntax::print(llvm::raw_ostream &OS, SyntaxPrintOptions Opts) const {
if (auto Raw = getRaw())
Raw->print(OS, Opts);
}
void Syntax::dump() const {
getRaw()->dump();
}
void Syntax::dump(llvm::raw_ostream &OS, unsigned Indent) const {
getRaw()->dump(OS, 0);
}
bool Syntax::isType() const {
return Data->isType();
}
bool Syntax::isDecl() const {
return Data->isDecl();
}
bool Syntax::isStmt() const {
return Data->isStmt();
}
bool Syntax::isExpr() const {
return Data->isExpr();
}
bool Syntax::isToken() const {
return getRaw()->isToken();
}
bool Syntax::isPattern() const {
return Data->isPattern();
}
bool Syntax::isUnknown() const {
return Data->isUnknown();
}
bool Syntax::isPresent() const {
return getRaw()->isPresent();
}
bool Syntax::isMissing() const {
return getRaw()->isMissing();
}
llvm::Optional<Syntax> Syntax::getParent() const {
auto ParentData = getData().getParent();
if (!ParentData) return llvm::None;
return llvm::Optional<Syntax> {
Syntax { Root, ParentData }
};
}
Syntax Syntax::getRoot() const {
return { Root, Root.get() };
}
size_t Syntax::getNumChildren() const {
return Data->getNumChildren();
}
llvm::Optional<Syntax> Syntax::getChild(const size_t N) const {
auto ChildData = Data->getChild(N);
if (!ChildData)
return llvm::None;
return Syntax {Root, ChildData.get()};
}
AbsolutePosition Syntax::getAbsolutePosition() const {
assert(getRoot().is<SourceFileSyntax>() &&
"Absolute position can only be calculated for nodes which has "
"SourceFile root");
AbsolutePosition Pos;
/// This visitor collects all of the nodes before this node to calculate its
/// offset from the begenning of the file.
class Visitor: public SyntaxVisitor {
AbsolutePosition &Pos;
const SyntaxData *Target;
bool Found = false;
public:
Visitor(AbsolutePosition &Pos, const SyntaxData *Target)
: Pos(Pos), Target(Target) {}
~Visitor() { assert(Found); }
void visitPre(Syntax Node) override {
// Check if this node is the target;
Found |= Node.getDataPointer() == Target;
}
void visit(TokenSyntax Node) override {
// Ignore missing node and ignore the nodes after this node.
if (Found || Node.isMissing())
return;
// Collect all the offsets.
Node.getRaw()->accumulateAbsolutePosition(Pos);
}
} Calculator(Pos, getDataPointer());
/// This visitor visit the first token node of this node to accumulate its
/// leading trivia. Therefore, the calculated absolute location will point
/// to the actual token start.
class FirstTokenFinder: public SyntaxVisitor {
AbsolutePosition &Pos;
bool Found = false;
public:
FirstTokenFinder(AbsolutePosition &Pos): Pos(Pos) {}
void visit(TokenSyntax Node) override {
if (Found || Node.isMissing())
return;
Found = true;
for (auto &Leader : Node.getRaw()->getLeadingTrivia())
Leader.accumulateAbsolutePosition(Pos);
}
} FTFinder(Pos);
// Visit the root to get all the nodes before this node.
getRoot().accept(Calculator);
// Visit this node to accumulate the leading trivia of its first token.
const_cast<Syntax*>(this)->accept(FTFinder);
return Pos;
}