Coverage Report

Created: 2026-06-15 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmSourceGroup.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmSourceGroup.h"
4
5
#include <utility>
6
7
#include <cm/memory>
8
9
#include "cmGeneratorExpression.h"
10
#include "cmStringAlgorithms.h"
11
12
class cmSourceGroupInternals
13
{
14
public:
15
  SourceGroupVector GroupChildren;
16
};
17
18
cmSourceGroup::cmSourceGroup(std::string name, char const* regex,
19
                             char const* parentName)
20
8
  : Name(std::move(name))
21
8
{
22
8
  this->Internal = cm::make_unique<cmSourceGroupInternals>();
23
8
  this->SetGroupRegex(regex);
24
8
  if (parentName) {
25
0
    this->FullName = cmStrCat(parentName, '\\');
26
0
  }
27
8
  this->FullName += this->Name;
28
8
}
29
30
8
cmSourceGroup::~cmSourceGroup() = default;
31
32
void cmSourceGroup::SetGroupRegex(char const* regex)
33
15
{
34
15
  if (regex) {
35
15
    this->GroupRegex.compile(regex);
36
15
  } else {
37
0
    this->GroupRegex.compile("^$");
38
0
  }
39
15
}
40
41
void cmSourceGroup::ResolveGenex(cmLocalGenerator* lg,
42
                                 std::string const& config)
43
0
{
44
0
  std::set<std::string> files;
45
46
0
  for (std::string const& file : this->GroupFiles) {
47
0
    files.emplace(cmGeneratorExpression::Evaluate(file, lg, config));
48
0
  }
49
50
0
  this->GroupFiles = std::move(files);
51
52
0
  if (!this->Internal) {
53
0
    return;
54
0
  }
55
56
0
  for (auto const& group : this->Internal->GroupChildren) {
57
0
    group->ResolveGenex(lg, config);
58
0
  }
59
0
}
60
61
void cmSourceGroup::AddGroupFile(std::string const& name)
62
0
{
63
0
  this->GroupFiles.insert(name);
64
0
}
65
66
std::string const& cmSourceGroup::GetName() const
67
49
{
68
49
  return this->Name;
69
49
}
70
71
std::string const& cmSourceGroup::GetFullName() const
72
0
{
73
0
  return this->FullName;
74
0
}
75
76
bool cmSourceGroup::MatchesRegex(std::string const& name) const
77
0
{
78
0
  cmsys::RegularExpressionMatch match;
79
0
  return this->GroupRegex.find(name.c_str(), match);
80
0
}
81
82
bool cmSourceGroup::MatchesFiles(std::string const& name) const
83
0
{
84
0
  return this->GroupFiles.find(name) != this->GroupFiles.cend();
85
0
}
86
87
std::set<std::string> const& cmSourceGroup::GetGroupFiles() const
88
0
{
89
0
  return this->GroupFiles;
90
0
}
91
92
void cmSourceGroup::AddChild(std::unique_ptr<cmSourceGroup> child)
93
0
{
94
0
  this->Internal->GroupChildren.push_back(std::move(child));
95
0
}
96
97
cmSourceGroup* cmSourceGroup::LookupChild(std::string const& name) const
98
0
{
99
0
  for (auto& group : this->Internal->GroupChildren) {
100
    // look if descendant is the one we're looking for
101
0
    if (group->GetName() == name) {
102
0
      return group.get(); // if so return it
103
0
    }
104
0
  }
105
106
  // if no child with this name was found return NULL
107
0
  return nullptr;
108
0
}
109
110
cmSourceGroup* cmSourceGroup::MatchChildrenFiles(std::string const& name)
111
0
{
112
0
  if (this->MatchesFiles(name)) {
113
0
    return this;
114
0
  }
115
0
  for (auto& group : this->Internal->GroupChildren) {
116
0
    cmSourceGroup* result = group->MatchChildrenFiles(name);
117
0
    if (result) {
118
0
      return result;
119
0
    }
120
0
  }
121
0
  return nullptr;
122
0
}
123
124
cmSourceGroup const* cmSourceGroup::MatchChildrenFiles(
125
  std::string const& name) const
126
0
{
127
0
  if (this->MatchesFiles(name)) {
128
0
    return this;
129
0
  }
130
0
  for (auto const& group : this->Internal->GroupChildren) {
131
0
    cmSourceGroup const* result = group->MatchChildrenFiles(name);
132
0
    if (result) {
133
0
      return result;
134
0
    }
135
0
  }
136
0
  return nullptr;
137
0
}
138
139
cmSourceGroup* cmSourceGroup::MatchChildrenRegex(std::string const& name) const
140
0
{
141
0
  for (auto& group : this->Internal->GroupChildren) {
142
0
    cmSourceGroup* result = group->MatchChildrenRegex(name);
143
0
    if (result) {
144
0
      return result;
145
0
    }
146
0
  }
147
0
  if (this->MatchesRegex(name)) {
148
0
    return const_cast<cmSourceGroup*>(this);
149
0
  }
150
151
0
  return nullptr;
152
0
}
153
154
SourceGroupVector const& cmSourceGroup::GetGroupChildren() const
155
0
{
156
0
  return this->Internal->GroupChildren;
157
0
}
158
159
/**
160
 * Find a source group whose regular expression matches the filename
161
 * part of the given source name.  Search backward through the list of
162
 * source groups, and take the first matching group found.  This way
163
 * non-inherited SOURCE_GROUP commands will have precedence over
164
 * inherited ones.
165
 */
166
cmSourceGroup* cmSourceGroup::FindSourceGroup(std::string const& source,
167
                                              SourceGroupVector const& groups)
168
0
{
169
  // First search for a group that lists the file explicitly.
170
0
  for (auto sg = groups.rbegin(); sg != groups.rend(); ++sg) {
171
0
    cmSourceGroup* result = (*sg)->MatchChildrenFiles(source);
172
0
    if (result) {
173
0
      return result;
174
0
    }
175
0
  }
176
177
  // Now search for a group whose regex matches the file.
178
0
  for (auto sg = groups.rbegin(); sg != groups.rend(); ++sg) {
179
0
    cmSourceGroup* result = (*sg)->MatchChildrenRegex(source);
180
0
    if (result) {
181
0
      return result;
182
0
    }
183
0
  }
184
185
  // Shouldn't get here, but just in case, return the default group.
186
0
  return groups.data()->get();
187
0
}
188
189
void cmSourceGroupFiles::Add(cmSourceGroup const* sg, cmSourceFile const* sf)
190
0
{
191
0
  this->SourceFiles[sg].push_back(sf);
192
0
}
193
194
std::vector<cmSourceFile const*> const& cmSourceGroupFiles::GetSourceFiles(
195
  cmSourceGroup const* sg) const
196
0
{
197
0
  auto i = this->SourceFiles.find(sg);
198
0
  if (i != this->SourceFiles.end()) {
199
0
    return i->second;
200
0
  }
201
0
  static std::vector<cmSourceFile const*> const empty;
202
0
  return empty;
203
0
}