Coverage Report

Created: 2026-02-09 06:05

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