1515
1616#include " llvm/Support/SpecialCaseList.h"
1717#include " llvm/ADT/STLExtras.h"
18+ #include " llvm/ADT/SetVector.h"
1819#include " llvm/ADT/StringExtras.h"
1920#include " llvm/ADT/StringRef.h"
2021#include " llvm/Support/LineIterator.h"
2122#include " llvm/Support/MemoryBuffer.h"
2223#include " llvm/Support/VirtualFileSystem.h"
24+ #include " llvm/Support/raw_ostream.h"
2325#include < algorithm>
2426#include < limits>
2527#include < memory>
@@ -63,12 +65,12 @@ void SpecialCaseList::RegexMatcher::preprocess(bool BySize) {
6365 }
6466}
6567
66- void SpecialCaseList::RegexMatcher::match (
67- StringRef Query,
68- llvm::function_ref<void (StringRef Rule, unsigned LineNo)> Cb) const {
68+ SpecialCaseList::Match
69+ SpecialCaseList::RegexMatcher::match (StringRef Query) const {
6970 for (const auto &R : reverse (RegExes))
7071 if (R.Rg .match (Query))
71- return Cb (R.Name , R.LineNo );
72+ return {R.Name , R.LineNo };
73+ return NotMatched;
7274}
7375
7476Error SpecialCaseList::GlobMatcher::insert (StringRef Pattern,
@@ -90,7 +92,7 @@ void SpecialCaseList::GlobMatcher::preprocess(bool BySize) {
9092 });
9193 }
9294
93- for (const auto &G : reverse (Globs)) {
95+ for (const auto &[Idx, G] : enumerate (Globs)) {
9496 StringRef Prefix = G.Pattern .prefix ();
9597 StringRef Suffix = G.Pattern .suffix ();
9698
@@ -102,26 +104,29 @@ void SpecialCaseList::GlobMatcher::preprocess(bool BySize) {
102104 // But only if substring is not empty. Searching this tree is more
103105 // expensive.
104106 auto &V = SubstrToGlob.emplace (Substr).first ->second ;
105- V.emplace_back (&G );
107+ V.emplace_back (Idx );
106108 continue ;
107109 }
108110 }
109111
110112 auto &SToGlob = PrefixSuffixToGlob.emplace (Prefix).first ->second ;
111113 auto &V = SToGlob.emplace (reverse (Suffix)).first ->second ;
112- V.emplace_back (&G );
114+ V.emplace_back (Idx );
113115 }
114116}
115117
116- void SpecialCaseList::GlobMatcher::match (
117- StringRef Query,
118- llvm::function_ref< void (StringRef Rule, unsigned LineNo)> Cb) const {
118+ SpecialCaseList::Match
119+ SpecialCaseList::GlobMatcher::match ( StringRef Query) const {
120+ int Best = - 1 ;
119121 if (!PrefixSuffixToGlob.empty ()) {
120122 for (const auto &[_, SToGlob] : PrefixSuffixToGlob.find_prefixes (Query)) {
121123 for (const auto &[_, V] : SToGlob.find_prefixes (reverse (Query))) {
122- for (const auto *G : V) {
123- if (G->Pattern .match (Query)) {
124- Cb (G->Name , G->LineNo );
124+ for (int Idx : reverse (V)) {
125+ if (Best > Idx)
126+ break ;
127+ const GlobMatcher::Glob &G = Globs[Idx];
128+ if (G.Pattern .match (Query)) {
129+ Best = Idx;
125130 // As soon as we find a match in the vector, we can break for this
126131 // vector, since the globs are already sorted by priority within the
127132 // prefix group. However, we continue searching other prefix groups
@@ -138,9 +143,12 @@ void SpecialCaseList::GlobMatcher::match(
138143 // possibilities. In most cases search will fail on first characters.
139144 for (StringRef Q = Query; !Q.empty (); Q = Q.drop_front ()) {
140145 for (const auto &[_, V] : SubstrToGlob.find_prefixes (Q)) {
141- for (const auto *G : V) {
142- if (G->Pattern .match (Query)) {
143- Cb (G->Name , G->LineNo );
146+ for (int Idx : reverse (V)) {
147+ if (Best > Idx)
148+ break ;
149+ const GlobMatcher::Glob &G = Globs[Idx];
150+ if (G.Pattern .match (Query)) {
151+ Best = Idx;
144152 // As soon as we find a match in the vector, we can break for this
145153 // vector, since the globs are already sorted by priority within the
146154 // prefix group. However, we continue searching other prefix groups
@@ -151,6 +159,9 @@ void SpecialCaseList::GlobMatcher::match(
151159 }
152160 }
153161 }
162+ if (Best < 0 )
163+ return NotMatched;
164+ return {Globs[Best].Name , Globs[Best].LineNo };
154165}
155166
156167SpecialCaseList::Matcher::Matcher (bool UseGlobs, bool RemoveDotSlash)
@@ -169,12 +180,11 @@ void SpecialCaseList::Matcher::preprocess(bool BySize) {
169180 return std::visit ([&](auto &V) { return V.preprocess (BySize); }, M);
170181}
171182
172- void SpecialCaseList::Matcher::match (
173- StringRef Query,
174- llvm::function_ref<void (StringRef Rule, unsigned LineNo)> Cb) const {
183+ SpecialCaseList::Match SpecialCaseList::Matcher::match (StringRef Query) const {
175184 if (RemoveDotSlash)
176185 Query = llvm::sys::path::remove_leading_dotslash (Query);
177- return std::visit ([&](auto &V) { return V.match (Query, Cb); }, M);
186+ return std::visit (
187+ [&](auto &V) -> SpecialCaseList::Match { return V.match (Query); }, M);
178188}
179189
180190// TODO: Refactor this to return Expected<...>
@@ -264,11 +274,12 @@ bool SpecialCaseList::parse(unsigned FileIdx, const MemoryBuffer *MB,
264274
265275 bool RemoveDotSlash = Version > 2 ;
266276
267- Section *CurrentSection ;
268- if (auto Err = addSection ( " * " , FileIdx, 1 , true ). moveInto (CurrentSection )) {
277+ auto ErrOrSection = addSection ( " * " , FileIdx, 1 , true ) ;
278+ if (auto Err = ErrOrSection. takeError ( )) {
269279 Error = toString (std::move (Err));
270280 return false ;
271281 }
282+ Section *CurrentSection = ErrOrSection.get ();
272283
273284 // This is the current list of prefixes for all existing users matching file
274285 // path. We may need parametrization in constructor in future.
@@ -290,12 +301,13 @@ bool SpecialCaseList::parse(unsigned FileIdx, const MemoryBuffer *MB,
290301 return false ;
291302 }
292303
293- if ( auto Err = addSection (Line. drop_front (). drop_back (), FileIdx, LineNo,
294- UseGlobs)
295- . moveInto (CurrentSection )) {
304+ auto ErrOrSection =
305+ addSection (Line. drop_front (). drop_back (), FileIdx, LineNo, UseGlobs);
306+ if ( auto Err = ErrOrSection. takeError ( )) {
296307 Error = toString (std::move (Err));
297308 return false ;
298309 }
310+ CurrentSection = ErrOrSection.get ();
299311 continue ;
300312 }
301313
@@ -348,6 +360,10 @@ SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
348360 return NotFound;
349361}
350362
363+ bool SpecialCaseList::Section::matchName (StringRef Name) const {
364+ return SectionMatcher.matchAny (Name);
365+ }
366+
351367const SpecialCaseList::Matcher *
352368SpecialCaseList::Section::findMatcher (StringRef Prefix,
353369 StringRef Category) const {
@@ -371,26 +387,21 @@ LLVM_ABI void SpecialCaseList::Section::preprocess(bool OrderBySize) {
371387unsigned SpecialCaseList::Section::getLastMatch (StringRef Prefix,
372388 StringRef Query,
373389 StringRef Category) const {
374- unsigned LastLine = 0 ;
375- if (const Matcher *M = findMatcher (Prefix, Category)) {
376- M->match (Query, [&](StringRef, unsigned LineNo) {
377- LastLine = std::max (LastLine, LineNo);
378- });
379- }
380- return LastLine;
390+ if (const Matcher *M = findMatcher (Prefix, Category))
391+ return M->match (Query).second ;
392+ return 0 ;
381393}
382394
383395StringRef SpecialCaseList::Section::getLongestMatch (StringRef Prefix,
384396 StringRef Query,
385397 StringRef Category) const {
386- StringRef LongestRule;
387- if (const Matcher *M = findMatcher (Prefix, Category)) {
388- M->match (Query, [&](StringRef Rule, unsigned ) {
389- if (LongestRule.size () < Rule.size ())
390- LongestRule = Rule;
391- });
392- }
393- return LongestRule;
398+ if (const Matcher *M = findMatcher (Prefix, Category))
399+ return M->match (Query).first ;
400+ return {};
401+ }
402+
403+ bool SpecialCaseList::Section::hasPrefix (StringRef Prefix) const {
404+ return Entries.find (Prefix) != Entries.end ();
394405}
395406
396407} // namespace llvm
0 commit comments