Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clangd/Selection.cpp @ 221:79ff65ed7e25
LLVM12 Original
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Jun 2021 19:15:29 +0900 |
parents | 0572611fdcc8 |
children | 5f17cb93ff66 |
comparison
equal
deleted
inserted
replaced
220:42394fc6a535 | 221:79ff65ed7e25 |
---|---|
33 | 33 |
34 namespace clang { | 34 namespace clang { |
35 namespace clangd { | 35 namespace clangd { |
36 namespace { | 36 namespace { |
37 using Node = SelectionTree::Node; | 37 using Node = SelectionTree::Node; |
38 using ast_type_traits::DynTypedNode; | |
39 | 38 |
40 // Measure the fraction of selections that were enabled by recovery AST. | 39 // Measure the fraction of selections that were enabled by recovery AST. |
41 void recordMetrics(const SelectionTree &S) { | 40 void recordMetrics(const SelectionTree &S, const LangOptions &Lang) { |
41 if (!trace::enabled()) | |
42 return; | |
43 const char *LanguageLabel = Lang.CPlusPlus ? "C++" : Lang.ObjC ? "ObjC" : "C"; | |
42 static constexpr trace::Metric SelectionUsedRecovery( | 44 static constexpr trace::Metric SelectionUsedRecovery( |
43 "selection_recovery", trace::Metric::Distribution); | 45 "selection_recovery", trace::Metric::Distribution, "language"); |
46 static constexpr trace::Metric RecoveryType( | |
47 "selection_recovery_type", trace::Metric::Distribution, "language"); | |
44 const auto *Common = S.commonAncestor(); | 48 const auto *Common = S.commonAncestor(); |
45 for (const auto *N = Common; N; N = N->Parent) { | 49 for (const auto *N = Common; N; N = N->Parent) { |
46 if (N->ASTNode.get<RecoveryExpr>()) { | 50 if (const auto *RE = N->ASTNode.get<RecoveryExpr>()) { |
47 SelectionUsedRecovery.record(1); // used recovery ast. | 51 SelectionUsedRecovery.record(1, LanguageLabel); // used recovery ast. |
52 RecoveryType.record(RE->isTypeDependent() ? 0 : 1, LanguageLabel); | |
48 return; | 53 return; |
49 } | 54 } |
50 } | 55 } |
51 if (Common) | 56 if (Common) |
52 SelectionUsedRecovery.record(0); // unused. | 57 SelectionUsedRecovery.record(0, LanguageLabel); // unused. |
53 } | 58 } |
54 | 59 |
55 // An IntervalSet maintains a set of disjoint subranges of an array. | 60 // An IntervalSet maintains a set of disjoint subranges of an array. |
56 // | 61 // |
57 // Initially, it contains the entire array. | 62 // Initially, it contains the entire array. |
75 IntervalSet(llvm::ArrayRef<T> Range) { UnclaimedRanges.insert(Range); } | 80 IntervalSet(llvm::ArrayRef<T> Range) { UnclaimedRanges.insert(Range); } |
76 | 81 |
77 // Removes the elements of Claim from the set, modifying or removing ranges | 82 // Removes the elements of Claim from the set, modifying or removing ranges |
78 // that overlap it. | 83 // that overlap it. |
79 // Returns the continuous subranges of Claim that were actually removed. | 84 // Returns the continuous subranges of Claim that were actually removed. |
80 llvm::SmallVector<llvm::ArrayRef<T>, 4> erase(llvm::ArrayRef<T> Claim) { | 85 llvm::SmallVector<llvm::ArrayRef<T>> erase(llvm::ArrayRef<T> Claim) { |
81 llvm::SmallVector<llvm::ArrayRef<T>, 4> Out; | 86 llvm::SmallVector<llvm::ArrayRef<T>> Out; |
82 if (Claim.empty()) | 87 if (Claim.empty()) |
83 return Out; | 88 return Out; |
84 | 89 |
85 // General case: | 90 // General case: |
86 // Claim: [-----------------] | 91 // Claim: [-----------------] |
215 }); | 220 }); |
216 const syntax::Token *SelLimit = std::partition_point( | 221 const syntax::Token *SelLimit = std::partition_point( |
217 SelFirst, AllSpelledTokens.end(), [&](const syntax::Token &Tok) { | 222 SelFirst, AllSpelledTokens.end(), [&](const syntax::Token &Tok) { |
218 return SM.getFileOffset(Tok.location()) < SelEnd; | 223 return SM.getFileOffset(Tok.location()) < SelEnd; |
219 }); | 224 }); |
225 auto Sel = llvm::makeArrayRef(SelFirst, SelLimit); | |
226 // Find which of these are preprocessed to nothing and should be ignored. | |
227 std::vector<bool> PPIgnored(Sel.size(), false); | |
228 for (const syntax::TokenBuffer::Expansion &X : | |
229 Buf.expansionsOverlapping(Sel)) { | |
230 if (X.Expanded.empty()) { | |
231 for (const syntax::Token &Tok : X.Spelled) { | |
232 if (&Tok >= SelFirst && &Tok < SelLimit) | |
233 PPIgnored[&Tok - SelFirst] = true; | |
234 } | |
235 } | |
236 } | |
220 // Precompute selectedness and offset for selected spelled tokens. | 237 // Precompute selectedness and offset for selected spelled tokens. |
221 for (const syntax::Token *T = SelFirst; T < SelLimit; ++T) { | 238 for (unsigned I = 0; I < Sel.size(); ++I) { |
222 if (shouldIgnore(*T)) | 239 if (shouldIgnore(Sel[I]) || PPIgnored[I]) |
223 continue; | 240 continue; |
224 SpelledTokens.emplace_back(); | 241 SpelledTokens.emplace_back(); |
225 Tok &S = SpelledTokens.back(); | 242 Tok &S = SpelledTokens.back(); |
226 S.Offset = SM.getFileOffset(T->location()); | 243 S.Offset = SM.getFileOffset(Sel[I].location()); |
227 if (S.Offset >= SelBegin && S.Offset + T->length() <= SelEnd) | 244 if (S.Offset >= SelBegin && S.Offset + Sel[I].length() <= SelEnd) |
228 S.Selected = SelectionTree::Complete; | 245 S.Selected = SelectionTree::Complete; |
229 else | 246 else |
230 S.Selected = SelectionTree::Partial; | 247 S.Selected = SelectionTree::Partial; |
231 } | 248 } |
232 } | 249 } |
462 return traverseNode(X, [&] { return Base::TraverseDecl(X); }); | 479 return traverseNode(X, [&] { return Base::TraverseDecl(X); }); |
463 } | 480 } |
464 bool TraverseTypeLoc(TypeLoc X) { | 481 bool TraverseTypeLoc(TypeLoc X) { |
465 return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); }); | 482 return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); }); |
466 } | 483 } |
484 bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &X) { | |
485 return traverseNode(&X, | |
486 [&] { return Base::TraverseTemplateArgumentLoc(X); }); | |
487 } | |
467 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc X) { | 488 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc X) { |
468 return traverseNode( | 489 return traverseNode( |
469 &X, [&] { return Base::TraverseNestedNameSpecifierLoc(X); }); | 490 &X, [&] { return Base::TraverseNestedNameSpecifierLoc(X); }); |
470 } | 491 } |
471 bool TraverseConstructorInitializer(CXXCtorInitializer *X) { | 492 bool TraverseConstructorInitializer(CXXCtorInitializer *X) { |
472 return traverseNode( | 493 return traverseNode( |
473 X, [&] { return Base::TraverseConstructorInitializer(X); }); | 494 X, [&] { return Base::TraverseConstructorInitializer(X); }); |
495 } | |
496 bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &X) { | |
497 return traverseNode(&X, [&] { return Base::TraverseCXXBaseSpecifier(X); }); | |
474 } | 498 } |
475 // Stmt is the same, but this form allows the data recursion optimization. | 499 // Stmt is the same, but this form allows the data recursion optimization. |
476 bool dataTraverseStmtPre(Stmt *X) { | 500 bool dataTraverseStmtPre(Stmt *X) { |
477 if (!X || isImplicit(X)) | 501 if (!X || isImplicit(X)) |
478 return false; | 502 return false; |
584 // An optimization for a common case: nodes outside macro expansions that | 608 // An optimization for a common case: nodes outside macro expansions that |
585 // don't intersect the selection may be recursively skipped. | 609 // don't intersect the selection may be recursively skipped. |
586 bool canSafelySkipNode(const DynTypedNode &N) { | 610 bool canSafelySkipNode(const DynTypedNode &N) { |
587 SourceRange S = N.getSourceRange(); | 611 SourceRange S = N.getSourceRange(); |
588 if (auto *TL = N.get<TypeLoc>()) { | 612 if (auto *TL = N.get<TypeLoc>()) { |
613 // FIXME: TypeLoc::getBeginLoc()/getEndLoc() are pretty fragile | |
614 // heuristics. We should consider only pruning critical TypeLoc nodes, to | |
615 // be more robust. | |
616 | |
589 // DeclTypeTypeLoc::getSourceRange() is incomplete, which would lead to | 617 // DeclTypeTypeLoc::getSourceRange() is incomplete, which would lead to |
590 // failing | 618 // failing |
591 // to descend into the child expression. | 619 // to descend into the child expression. |
592 // decltype(2+2); | 620 // decltype(2+2); |
593 // ~~~~~~~~~~~~~ <-- correct range | 621 // ~~~~~~~~~~~~~ <-- correct range |
595 // ~~~~~~~~~~~~ <-- range with this hack(i.e, missing closing paren) | 623 // ~~~~~~~~~~~~ <-- range with this hack(i.e, missing closing paren) |
596 // FIXME: Alter DecltypeTypeLoc to contain parentheses locations and get | 624 // FIXME: Alter DecltypeTypeLoc to contain parentheses locations and get |
597 // rid of this patch. | 625 // rid of this patch. |
598 if (auto DT = TL->getAs<DecltypeTypeLoc>()) | 626 if (auto DT = TL->getAs<DecltypeTypeLoc>()) |
599 S.setEnd(DT.getUnderlyingExpr()->getEndLoc()); | 627 S.setEnd(DT.getUnderlyingExpr()->getEndLoc()); |
628 // AttributedTypeLoc may point to the attribute's range, NOT the modified | |
629 // type's range. | |
630 if (auto AT = TL->getAs<AttributedTypeLoc>()) | |
631 S = AT.getModifiedLoc().getSourceRange(); | |
600 } | 632 } |
601 if (!SelChecker.mayHit(S)) { | 633 if (!SelChecker.mayHit(S)) { |
602 dlog("{1}skip: {0}", printNodeToString(N, PrintPolicy), indent()); | 634 dlog("{1}skip: {0}", printNodeToString(N, PrintPolicy), indent()); |
603 dlog("{1}skipped range = {0}", S.printToString(SM), indent(1)); | 635 dlog("{1}skipped range = {0}", S.printToString(SM), indent(1)); |
604 return true; | 636 return true; |
805 dlog("Computing selection for {0}", | 837 dlog("Computing selection for {0}", |
806 SourceRange(SM.getComposedLoc(FID, Begin), SM.getComposedLoc(FID, End)) | 838 SourceRange(SM.getComposedLoc(FID, Begin), SM.getComposedLoc(FID, End)) |
807 .printToString(SM)); | 839 .printToString(SM)); |
808 Nodes = SelectionVisitor::collect(AST, Tokens, PrintPolicy, Begin, End, FID); | 840 Nodes = SelectionVisitor::collect(AST, Tokens, PrintPolicy, Begin, End, FID); |
809 Root = Nodes.empty() ? nullptr : &Nodes.front(); | 841 Root = Nodes.empty() ? nullptr : &Nodes.front(); |
810 recordMetrics(*this); | 842 recordMetrics(*this, AST.getLangOpts()); |
811 dlog("Built selection tree\n{0}", *this); | 843 dlog("Built selection tree\n{0}", *this); |
812 } | 844 } |
813 | 845 |
814 const Node *SelectionTree::commonAncestor() const { | 846 const Node *SelectionTree::commonAncestor() const { |
815 const Node *Ancestor = Root; | 847 const Node *Ancestor = Root; |