mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -37,7 +37,6 @@
|
||||
#include "swift/IDE/SyntaxModel.h"
|
||||
#include "swift/Subsystems.h"
|
||||
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
|
||||
#include "swift/Syntax/SyntaxClassifier.h"
|
||||
#include "swift/Syntax/SyntaxNodes.h"
|
||||
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@@ -559,122 +558,6 @@ struct SwiftSyntaxMap {
|
||||
}
|
||||
};
|
||||
|
||||
class SyntaxToSyntaxMapConverter : public SyntaxVisitor {
|
||||
SwiftSyntaxMap &SyntaxMap;
|
||||
|
||||
std::map<SyntaxNodeId, SyntaxClassification> TokenClassifications;
|
||||
|
||||
public:
|
||||
SyntaxToSyntaxMapConverter(
|
||||
SwiftSyntaxMap &SyntaxMap,
|
||||
std::map<SyntaxNodeId, SyntaxClassification> TokenClassifications)
|
||||
: SyntaxMap(SyntaxMap), TokenClassifications(TokenClassifications) {}
|
||||
|
||||
private:
|
||||
void visitTrivia(Trivia Trivia, unsigned Offset) {
|
||||
for (auto TriviaPiece : Trivia) {
|
||||
visitTriviaPiece(TriviaPiece, Offset);
|
||||
Offset += TriviaPiece.getTextLength();
|
||||
}
|
||||
}
|
||||
|
||||
void visitTriviaPiece(TriviaPiece TriviaPiece, unsigned Offset) {
|
||||
llvm::Optional<SyntaxNodeKind> Kind;
|
||||
switch (TriviaPiece.getKind()) {
|
||||
case TriviaKind::Space:
|
||||
case TriviaKind::Tab:
|
||||
case TriviaKind::VerticalTab:
|
||||
case TriviaKind::Formfeed:
|
||||
case TriviaKind::Newline:
|
||||
case TriviaKind::CarriageReturn:
|
||||
case TriviaKind::CarriageReturnLineFeed:
|
||||
case swift::syntax::TriviaKind::Backtick:
|
||||
case TriviaKind::GarbageText:
|
||||
Kind = llvm::None;
|
||||
break;
|
||||
case swift::syntax::TriviaKind::LineComment:
|
||||
Kind = SyntaxNodeKind::CommentLine;
|
||||
break;
|
||||
case TriviaKind::BlockComment:
|
||||
Kind = SyntaxNodeKind::CommentBlock;
|
||||
break;
|
||||
case TriviaKind::DocLineComment:
|
||||
Kind = SyntaxNodeKind::DocCommentLine;
|
||||
break;
|
||||
case TriviaKind::DocBlockComment:
|
||||
Kind = SyntaxNodeKind::DocCommentBlock;
|
||||
break;
|
||||
}
|
||||
if (Kind.hasValue()) {
|
||||
SwiftSyntaxToken Token(Offset, TriviaPiece.getTextLength(),
|
||||
Kind.getValue());
|
||||
SyntaxMap.addToken(Token);
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Optional<SyntaxNodeKind>
|
||||
getKindForSyntaxClassification(SyntaxClassification Classification) const {
|
||||
// FIXME: We should really use the same enum so that the conversion is not
|
||||
// necessary
|
||||
switch (Classification) {
|
||||
case SyntaxClassification::None:
|
||||
return llvm::None;
|
||||
case SyntaxClassification::Keyword:
|
||||
return SyntaxNodeKind::Keyword;
|
||||
case SyntaxClassification::Identifier:
|
||||
return SyntaxNodeKind::Identifier;
|
||||
case SyntaxClassification::DollarIdentifier:
|
||||
return SyntaxNodeKind::DollarIdent;
|
||||
case SyntaxClassification::IntegerLiteral:
|
||||
return SyntaxNodeKind::Integer;
|
||||
case SyntaxClassification::FloatingLiteral:
|
||||
return SyntaxNodeKind::Floating;
|
||||
case SyntaxClassification::StringLiteral:
|
||||
return SyntaxNodeKind::String;
|
||||
case SyntaxClassification::StringInterpolationAnchor:
|
||||
return SyntaxNodeKind::StringInterpolationAnchor;
|
||||
case SyntaxClassification::TypeIdentifier:
|
||||
return SyntaxNodeKind::TypeId;
|
||||
case SyntaxClassification::BuildConfigKeyword:
|
||||
return SyntaxNodeKind::BuildConfigKeyword;
|
||||
case SyntaxClassification::BuildConfigId:
|
||||
return SyntaxNodeKind::BuildConfigId;
|
||||
case SyntaxClassification::PoundDirectiveKeyword:
|
||||
return SyntaxNodeKind::PoundDirectiveKeyword;
|
||||
case SyntaxClassification::Attribute:
|
||||
return SyntaxNodeKind::AttributeBuiltin;
|
||||
case SyntaxClassification::EditorPlaceholder:
|
||||
return SyntaxNodeKind::EditorPlaceholder;
|
||||
case SyntaxClassification::ObjectLiteral:
|
||||
return SyntaxNodeKind::ObjectLiteral;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(TokenSyntax Token) override {
|
||||
if (Token.isMissing())
|
||||
return;
|
||||
|
||||
auto LeadingTriviaOffset =
|
||||
Token.getAbsolutePositionBeforeLeadingTrivia().getOffset();
|
||||
visitTrivia(Token.getLeadingTrivia(), LeadingTriviaOffset);
|
||||
|
||||
SyntaxClassification Classification = TokenClassifications[Token.getId()];
|
||||
auto Kind = getKindForSyntaxClassification(Classification);
|
||||
unsigned TokenStart = Token.getAbsolutePosition().getOffset();
|
||||
unsigned TokenLength = Token.getRaw()->getTokenText().size();
|
||||
if (Kind.hasValue() && TokenLength > 0) {
|
||||
SwiftSyntaxToken Token(TokenStart, TokenLength, Kind.getValue());
|
||||
SyntaxMap.addToken(Token);
|
||||
}
|
||||
|
||||
auto TrailingTriviaOffset = TokenStart + TokenLength;
|
||||
visitTrivia(Token.getTrailingTrivia(), TrailingTriviaOffset);
|
||||
}
|
||||
|
||||
public:
|
||||
void writeToSyntaxMap(Syntax Node) { Node.accept(*this); }
|
||||
};
|
||||
|
||||
struct EditorConsumerSyntaxMapEntry {
|
||||
unsigned Offset;
|
||||
unsigned Length;
|
||||
@@ -1918,14 +1801,21 @@ void SwiftEditorDocument::readSyntaxInfo(EditorConsumer &Consumer) {
|
||||
|
||||
SwiftSyntaxMap NewMap = SwiftSyntaxMap(Impl.SyntaxMap.Tokens.size() + 16);
|
||||
|
||||
if (Consumer.forceLibSyntaxBasedProcessing()) {
|
||||
if (Consumer.syntaxTreeEnabled()) {
|
||||
auto SyntaxTree = Impl.SyntaxInfo->getSourceFile().getSyntaxRoot();
|
||||
|
||||
SyntaxClassifier Classifier;
|
||||
auto Classification = Classifier.classify(SyntaxTree);
|
||||
SyntaxToSyntaxMapConverter Printer(NewMap, Classification);
|
||||
Printer.writeToSyntaxMap(SyntaxTree);
|
||||
Impl.SyntaxTree.emplace(SyntaxTree);
|
||||
if (Consumer.syntaxMapEnabled()) {
|
||||
Consumer.handleRequestError(
|
||||
"Retrieving both a syntax map and a syntax tree at the same time is "
|
||||
"not supported. Use the SyntaxClassifier in swiftSyntax to generate "
|
||||
"the syntax map on the Swift side.");
|
||||
}
|
||||
if (Consumer.documentStructureEnabled()) {
|
||||
Consumer.handleRequestError(
|
||||
"Retrieving both the document structure and a syntax tree at the "
|
||||
"same time is not supported. Use the syntax tree to compute the "
|
||||
"document structure.");
|
||||
}
|
||||
} else {
|
||||
ide::SyntaxModelContext ModelContext(Impl.SyntaxInfo->getSourceFile());
|
||||
|
||||
@@ -1933,28 +1823,28 @@ void SwiftEditorDocument::readSyntaxInfo(EditorConsumer &Consumer) {
|
||||
NewMap, Impl.SyntaxInfo->getSourceManager(), Consumer,
|
||||
Impl.SyntaxInfo->getBufferID());
|
||||
ModelContext.walk(SyntaxWalker);
|
||||
}
|
||||
|
||||
bool SawChanges = true;
|
||||
if (Impl.Edited) {
|
||||
// We're ansering an edit request. Report all highlighted token ranges not
|
||||
// in the previous syntax map to the Consumer and extend the AffectedRange
|
||||
// to contain all added/removed token ranges.
|
||||
SawChanges = NewMap.forEachChanged(Impl.SyntaxMap, Impl.AffectedRange,
|
||||
Consumer);
|
||||
} else {
|
||||
// The is an open/initialise. Report all highlighted token ranges to the
|
||||
// Consumer.
|
||||
NewMap.forEach(Consumer);
|
||||
}
|
||||
Impl.SyntaxMap = std::move(NewMap);
|
||||
bool SawChanges = true;
|
||||
if (Impl.Edited) {
|
||||
// We're ansering an edit request. Report all highlighted token ranges not
|
||||
// in the previous syntax map to the Consumer and extend the AffectedRange
|
||||
// to contain all added/removed token ranges.
|
||||
SawChanges =
|
||||
NewMap.forEachChanged(Impl.SyntaxMap, Impl.AffectedRange, Consumer);
|
||||
} else {
|
||||
// The is an open/initialise. Report all highlighted token ranges to the
|
||||
// Consumer.
|
||||
NewMap.forEach(Consumer);
|
||||
}
|
||||
Impl.SyntaxMap = std::move(NewMap);
|
||||
|
||||
// Recording an affected length of 0 still results in the client updating its
|
||||
// copy of the syntax map (by clearning all tokens on the line of the affected
|
||||
// offset). We need to not record it at all to signal a no-op.
|
||||
if (SawChanges)
|
||||
Consumer.recordAffectedRange(Impl.AffectedRange->Offset,
|
||||
Impl.AffectedRange->length());
|
||||
// Recording an affected length of 0 still results in the client updating
|
||||
// its copy of the syntax map (by clearning all tokens on the line of the
|
||||
// affected offset). We need to not record it at all to signal a no-op.
|
||||
if (SawChanges)
|
||||
Consumer.recordAffectedRange(Impl.AffectedRange->Offset,
|
||||
Impl.AffectedRange->length());
|
||||
}
|
||||
}
|
||||
|
||||
void SwiftEditorDocument::readSemanticInfo(ImmutableTextSnapshotRef Snapshot,
|
||||
@@ -2189,13 +2079,11 @@ void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
|
||||
ArrayRef<const char *> Args) {
|
||||
|
||||
ImmutableTextSnapshotRef Snapshot = nullptr;
|
||||
const bool BuildSyntaxTree =
|
||||
Consumer.syntaxTreeEnabled() || Consumer.forceLibSyntaxBasedProcessing();
|
||||
auto EditorDoc = EditorDocuments.getByUnresolvedName(Name);
|
||||
if (!EditorDoc) {
|
||||
EditorDoc = new SwiftEditorDocument(Name, *this);
|
||||
Snapshot = EditorDoc->initializeText(Buf, Args);
|
||||
EditorDoc->parse(Snapshot, *this, BuildSyntaxTree);
|
||||
EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled());
|
||||
if (EditorDocuments.getOrUpdate(Name, *this, EditorDoc)) {
|
||||
// Document already exists, re-initialize it. This should only happen
|
||||
// if we get OPEN request while the previous document is not closed.
|
||||
@@ -2208,7 +2096,7 @@ void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
|
||||
|
||||
if (!Snapshot) {
|
||||
Snapshot = EditorDoc->initializeText(Buf, Args);
|
||||
EditorDoc->parse(Snapshot, *this, BuildSyntaxTree);
|
||||
EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled());
|
||||
}
|
||||
|
||||
if (Consumer.needsSemanticInfo()) {
|
||||
@@ -2354,14 +2242,9 @@ void SwiftLangSupport::editorReplaceText(StringRef Name,
|
||||
Snapshot = EditorDoc->replaceText(Offset, Length, Buf,
|
||||
Consumer.needsSemanticInfo());
|
||||
assert(Snapshot);
|
||||
bool BuildSyntaxTree = Consumer.syntaxTreeEnabled() ||
|
||||
Consumer.forceLibSyntaxBasedProcessing();
|
||||
|
||||
llvm::Optional<SyntaxParsingCache> SyntaxCache = llvm::None;
|
||||
bool IncrementalSyntaxParsing = Consumer.forceLibSyntaxBasedProcessing() ||
|
||||
Consumer.syntaxTreeTransferMode() ==
|
||||
SyntaxTreeTransferMode::Incremental;
|
||||
if (EditorDoc->getSyntaxTree().hasValue() && IncrementalSyntaxParsing) {
|
||||
if (EditorDoc->getSyntaxTree().hasValue()) {
|
||||
SyntaxCache.emplace(EditorDoc->getSyntaxTree().getValue());
|
||||
SyntaxCache->addEdit(Offset, Offset + Length, Buf->getBufferSize());
|
||||
}
|
||||
@@ -2370,7 +2253,8 @@ void SwiftLangSupport::editorReplaceText(StringRef Name,
|
||||
if (SyntaxCache.hasValue()) {
|
||||
SyntaxCachePtr = SyntaxCache.getPointer();
|
||||
}
|
||||
EditorDoc->parse(Snapshot, *this, BuildSyntaxTree, SyntaxCachePtr);
|
||||
EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled(),
|
||||
SyntaxCachePtr);
|
||||
EditorDoc->readSyntaxInfo(Consumer);
|
||||
|
||||
// Log reuse information
|
||||
|
||||
Reference in New Issue
Block a user