This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 460ac63f Remove empty SCR @Properties annotation after migration
460ac63f is described below
commit 460ac63f0f735be56eb1a7fcc786ffa75b6a79e0
Author: Konrad Windszus <[email protected]>
AuthorDate: Sat May 9 17:42:19 2026 +0200
Remove empty SCR @Properties annotation after migration
---
.../scripts/migrate_annotations.py | 40 +++++++++++++++++++++
.../scripts/tests/test_migrate_annotations.py | 42 ++++++++++++++++++++++
2 files changed, 82 insertions(+)
diff --git a/skills/osgi-scr-migrator/scripts/migrate_annotations.py
b/skills/osgi-scr-migrator/scripts/migrate_annotations.py
index 31e9eb6c..3378f110 100755
--- a/skills/osgi-scr-migrator/scripts/migrate_annotations.py
+++ b/skills/osgi-scr-migrator/scripts/migrate_annotations.py
@@ -310,6 +310,7 @@ class AnnotationMigrator:
self._generate_metatype_config()
self._update_imports()
+ self._cleanup_empty_properties_annotations()
return '\n'.join(self.lines), self.changes_made
except Exception as e:
@@ -475,6 +476,7 @@ class AnnotationMigrator:
'org.apache.felix.scr.annotations.Deactivate':
'org.osgi.service.component.annotations.Deactivate',
'org.apache.felix.scr.annotations.Modified':
'org.osgi.service.component.annotations.Modified',
'org.apache.felix.scr.annotations.Property': None,
+ 'org.apache.felix.scr.annotations.Properties': None,
'org.apache.felix.scr.annotations.Reference':
'org.osgi.service.component.annotations.Reference',
'org.apache.felix.scr.annotations.ReferenceCardinality':
'org.osgi.service.component.annotations.ReferenceCardinality',
'org.apache.felix.scr.annotations.ReferencePolicy':
'org.osgi.service.component.annotations.ReferencePolicy',
@@ -1104,6 +1106,44 @@ class AnnotationMigrator:
self.lines.insert(insert_idx, f'import {new_import};')
insert_idx += 1
+ def _cleanup_empty_properties_annotations(self):
+ """Remove empty Felix SCR @Properties container annotations.
+
+ This cleanup is run after @Property annotations are removed, so
containers
+ that become empty do not remain in migrated code.
+ """
+ i = 0
+ while i < len(self.lines):
+ line = self.lines[i]
+
+ if '@Properties' in line and not line.strip().startswith('//'):
+ annotation = line
+ paren_count = line.count('(') - line.count(')')
+ annotation_lines = [i]
+ j = i + 1
+
+ while paren_count > 0 and j < len(self.lines):
+ annotation += ' ' + self.lines[j].strip()
+ annotation_lines.append(j)
+ paren_count += self.lines[j].count('(') -
self.lines[j].count(')')
+ j += 1
+
+ compact = re.sub(r'\s+', '', annotation)
+ empty_forms = {
+ '@Properties',
+ '@Properties()',
+ '@Properties({})',
+ '@Properties(value={})',
+ }
+
+ if compact in empty_forms:
+ for idx in reversed(annotation_lines):
+ del self.lines[idx]
+ self.changes_made = True
+ continue
+
+ i += 1
+
def migrate_file(file_path: Path, dry_run: bool = False, stats: MigrationStats
= None) -> bool:
"""Migrate a single Java file."""
diff --git a/skills/osgi-scr-migrator/scripts/tests/test_migrate_annotations.py
b/skills/osgi-scr-migrator/scripts/tests/test_migrate_annotations.py
index 598d8458..8c4221b6 100644
--- a/skills/osgi-scr-migrator/scripts/tests/test_migrate_annotations.py
+++ b/skills/osgi-scr-migrator/scripts/tests/test_migrate_annotations.py
@@ -411,6 +411,48 @@ public class MyService {
self.assertIn('org.osgi.service.component.propertytypes.ServiceVendor',
new_content)
self.assertIn('org.osgi.service.component.propertytypes.ServiceRanking',
new_content)
+ def test_empty_properties_container_removed(self):
+ """Test that empty @Properties is removed after property migration."""
+ content = '''package com.example;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+
+@Component
+@Properties({
+ @Property(name = "service.vendor", value = "Apache Software Foundation")
+})
+public class MyService {
+}
+'''
+ stats = MigrationStats()
+ migrator = AnnotationMigrator(content, Path("test.java"), stats)
+ new_content, changed = migrator.migrate()
+
+ self.assertTrue(changed)
+ self.assertNotIn('@Properties', new_content)
+ self.assertNotIn('@Property', new_content)
+
+ def test_preexisting_empty_properties_removed(self):
+ """Test that pre-existing empty @Properties annotation is cleaned
up."""
+ content = '''package com.example;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+
+@Component
+@Properties(value = { })
+public class MyService {
+}
+'''
+ stats = MigrationStats()
+ migrator = AnnotationMigrator(content, Path("test.java"), stats)
+ new_content, changed = migrator.migrate()
+
+ self.assertTrue(changed)
+ self.assertNotIn('@Properties', new_content)
+
class TestReferenceMigration(unittest.TestCase):
"""Test @Reference migration."""