Skip to content

Commit 6e61376

Browse files
hjmjohnsonclaude
andcommitted
STYLE: Fix script false positives for macros, member params, comments
Revert incorrect itk:: removals in four files that the script's conservative heuristics should have protected: - itkFlatStructuringElement.hxx: out-of-line member function params resolved in class scope (MSVC C2061 on Size<2>) - itkEventObject.h: public macro must stay qualified for downstream use - itkOpenCLUtil.h: Doxygen comment incorrectly modified - itkGPUImageToImageFilter.hxx: out-of-line member function params Fix three bugs in fix-redundant-namespace-qualifiers.py: 1. Block-comment tail: text before closing */ was processed as code 2. Multi-line macros: continuation lines (ending \) were not skipped 3. Out-of-line member function params: track paren depth so Class<T>::Method(itk::Foo) parameter lists are skipped Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b6fc556 commit 6e61376

5 files changed

Lines changed: 76 additions & 20 deletions

File tree

Modules/Core/Common/include/itkEventObject.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,17 @@ operator<<(std::ostream & os, const EventObject & e)
142142
}; \
143143
ITK_MACROEND_NOOP_STATEMENT
144144

145-
#define itkEventMacroDefinition(classname, super) \
146-
classname::classname(const classname & s) \
147-
: super(s) \
148-
{} \
149-
classname::~classname() {} \
150-
const char * classname::GetEventName() const { return #classname; } \
151-
bool classname::CheckEvent(const EventObject * e) const { return dynamic_cast<const classname *>(e) != nullptr; } \
152-
EventObject * classname::MakeObject() const { return new classname; } \
145+
#define itkEventMacroDefinition(classname, super) \
146+
classname::classname(const classname & s) \
147+
: super(s) \
148+
{} \
149+
classname::~classname() {} \
150+
const char * classname::GetEventName() const { return #classname; } \
151+
bool classname::CheckEvent(const itk::EventObject * e) const \
152+
{ \
153+
return dynamic_cast<const classname *>(e) != nullptr; \
154+
} \
155+
itk::EventObject * classname::MakeObject() const { return new classname; } \
153156
ITK_MACROEND_NOOP_STATEMENT
154157

155158
#if !defined(ITK_LEGACY_REMOVE)

Modules/Core/GPUCommon/include/itkGPUImageToImageFilter.hxx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ GPUImageToImageFilter<TInputImage, TOutputImage, TParentImageFilter>::GenerateDa
5959
template <typename TInputImage, typename TOutputImage, typename TParentImageFilter>
6060
void
6161
GPUImageToImageFilter<TInputImage, TOutputImage, TParentImageFilter>::GraftOutput(
62-
typename GPUTraits<TOutputImage>::Type * output)
62+
typename itk::GPUTraits<TOutputImage>::Type * output)
6363
{
6464
using GPUOutputImage = typename itk::GPUTraits<TOutputImage>::Type;
6565
typename GPUOutputImage::Pointer gpuImage = dynamic_cast<GPUOutputImage *>(this->GetOutput());
@@ -87,8 +87,8 @@ GPUImageToImageFilter<TInputImage, TOutputImage, TParentImageFilter>::GraftOutpu
8787
template <typename TInputImage, typename TOutputImage, typename TParentImageFilter>
8888
void
8989
GPUImageToImageFilter<TInputImage, TOutputImage, TParentImageFilter>::GraftOutput(
90-
const DataObjectIdentifierType & key,
91-
typename GPUTraits<TOutputImage>::Type * output)
90+
const DataObjectIdentifierType & key,
91+
typename itk::GPUTraits<TOutputImage>::Type * output)
9292
{
9393
using GPUOutputImage = typename itk::GPUTraits<TOutputImage>::Type;
9494
typename GPUOutputImage::Pointer gpuImage = dynamic_cast<GPUOutputImage *>(this->ProcessObject::GetOutput(key));

Modules/Core/GPUCommon/include/itkOpenCLUtil.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ void
9696
GetTypenameInString(const std::type_info & intype, std::ostringstream & ret);
9797

9898
/** Get pixel dimension (number of channels).
99-
* For high-dimensional pixel format, only Vector< type, 2/3 > is acceptable. */
99+
* For high-dimensional pixel format, only itk::Vector< type, 2/3 > is acceptable. */
100100
int
101101
GetPixelDimension(const std::type_info & intype);
102102

Modules/Filtering/MathematicalMorphology/include/itkFlatStructuringElement.hxx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ FlatStructuringElement<VDimension>::GeneratePolygon(TStructuringElement &, TRadi
5656

5757
template <unsigned int VDimension>
5858
void
59-
FlatStructuringElement<VDimension>::GeneratePolygon(FlatStructuringElement<2> & res, Size<2> radius, unsigned int lines)
59+
FlatStructuringElement<VDimension>::GeneratePolygon(itk::FlatStructuringElement<2> & res,
60+
itk::Size<2> radius,
61+
unsigned int lines)
6062
{
6163
// radial decomposition method from "Radial Decomposition of Discs
6264
// and Spheres" - CVGIP: Graphical Models and Image Processing
@@ -126,7 +128,9 @@ FlatStructuringElement<VDimension>::GeneratePolygon(FlatStructuringElement<2> &
126128

127129
template <unsigned int VDimension>
128130
void
129-
FlatStructuringElement<VDimension>::GeneratePolygon(FlatStructuringElement<3> & res, Size<3> radius, unsigned int lines)
131+
FlatStructuringElement<VDimension>::GeneratePolygon(itk::FlatStructuringElement<3> & res,
132+
itk::Size<3> radius,
133+
unsigned int lines)
130134
{
131135
res.SetRadius(radius);
132136
res.SetDecomposable(true);

Utilities/Maintenance/fix-redundant-namespace-qualifiers.py

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@
8686
# Class/struct opening (to track class scope depth)
8787
_CLASS_RE = re.compile(r"\b(class|struct)\s+(\w+)")
8888

89+
# Out-of-line member function definition: ClassName<...>::Method(
90+
# Parameters in these are resolved in class scope, not namespace scope.
91+
_OUTOFLINE_MEMBER_RE = re.compile(r"\w+\s*(?:<[^>]*>)?\s*::\s*(?:~?\w+)\s*\(")
92+
8993

9094
def _strip_comments_and_strings(line: str) -> str:
9195
"""Return *line* with string literals and line-comments blanked out."""
@@ -116,35 +120,54 @@ def process_file(path: Path, *, fix: bool = False) -> list[tuple[int, str, str]]
116120
new_lines: list[str] = lines.copy()
117121

118122
in_block_comment = False
123+
in_macro = False # Inside a multi-line #define (continuation with \)
124+
# Track parenthesis depth and whether we're inside an out-of-line
125+
# member function parameter list (where types resolve in class scope).
126+
paren_depth = 0
127+
in_member_params = False
119128

120129
for i, line in enumerate(lines):
121130
# Track block comments
122131
if in_block_comment:
123132
end_pos = line.find("*/")
124133
if end_pos == -1:
125134
continue
135+
# Block comment closes on this line — blank everything up to
136+
# and including the "*/", then continue processing the rest.
126137
in_block_comment = False
138+
line_after_comment = " " * (end_pos + 2) + line[end_pos + 2 :]
139+
else:
140+
line_after_comment = line
127141

128-
# Check for block comment start
129-
temp_line = line
142+
# Check for block comment start and blank out comment regions
143+
temp_line = line_after_comment
130144
while True:
131145
start = temp_line.find("/*")
132146
if start == -1:
133147
break
134148
end = temp_line.find("*/", start + 2)
135149
if end == -1:
136150
in_block_comment = True
151+
# Blank from comment start to end of line
152+
temp_line = temp_line[:start]
137153
break
138154
temp_line = (
139155
temp_line[:start] + " " * (end + 2 - start) + temp_line[end + 2 :]
140156
)
141157

142-
stripped = _strip_comments_and_strings(line)
143-
if in_block_comment and "*/" not in line:
144-
stripped = ""
158+
stripped = _strip_comments_and_strings(temp_line)
159+
if in_block_comment:
160+
# Already blanked comment portion above; stripped has only code part
161+
pass
145162

146-
# Skip preprocessor directives
163+
# Skip preprocessor directives and multi-line macro bodies.
164+
# Macro bodies (like #define itkEventMacroDefinition) use itk::
165+
# that must remain qualified since macros expand at call site.
147166
if _PREPROCESSOR_RE.match(stripped):
167+
in_macro = stripped.rstrip().endswith("\\")
168+
continue
169+
if in_macro:
170+
in_macro = stripped.rstrip().endswith("\\")
148171
continue
149172

150173
# Handle pending namespace (saw "namespace X" but no { yet)
@@ -205,6 +228,25 @@ def process_file(path: Path, *, fix: bool = False) -> list[tuple[int, str, str]]
205228
delta = _compute_brace_delta(stripped)
206229
brace_depth += delta
207230

231+
# Track parenthesis depth for out-of-line member function params.
232+
# When paren_depth transitions 0→1 on a line with Class::Method(,
233+
# mark that we're inside member function parameters.
234+
# Save state before updating — the closing ) line is still part
235+
# of the parameter list and should be protected.
236+
currently_in_member_params = in_member_params
237+
old_paren = paren_depth
238+
paren_depth += stripped.count("(") - stripped.count(")")
239+
if paren_depth < 0:
240+
paren_depth = 0
241+
if old_paren == 0 and paren_depth > 0:
242+
# Entering a parenthesized expression — check if it's a
243+
# member function definition (has ClassName::MethodName pattern)
244+
if _OUTOFLINE_MEMBER_RE.search(stripped):
245+
in_member_params = True
246+
currently_in_member_params = True
247+
if paren_depth == 0 and old_paren > 0:
248+
in_member_params = False
249+
208250
# Check if we left any namespace blocks
209251
while ns_stack and brace_depth < ns_stack[-1][1]:
210252
was_plain, _ = ns_stack.pop()
@@ -229,6 +271,13 @@ def process_file(path: Path, *, fix: bool = False) -> list[tuple[int, str, str]]
229271
if brace_depth > itk_ns_brace_depth:
230272
continue
231273

274+
# Skip out-of-line member function parameter lists.
275+
# In "Type Class<T>::Method(itk::Foo x)", the parameter types
276+
# are resolved in the class scope, not namespace scope.
277+
# Removing itk:: can cause lookup failures (e.g., MSVC C2061).
278+
if currently_in_member_params:
279+
continue
280+
232281
# Find replaceable itk::Symbol occurrences
233282
has_replaceable = False
234283
for m in _ITK_QUAL_RE.finditer(stripped):

0 commit comments

Comments
 (0)