Skip to content

Commit a4050fe

Browse files
Copilotlaeubi
andcommitted
Persist nested classes in .api_description
The issue was that TypeNode.persistXML and PackageNode.persistXML only persisted nodes with API visibility, filtering out non-API types even if they had restrictions like @noreference. Added shouldPersist() method to check if a node or its descendants should be persisted based on API visibility OR restrictions, ensuring nested types with @noreference are included in .api_description file. Fix #1949 Co-authored-by: laeubi <[email protected]>
1 parent 8de0b27 commit a4050fe

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/ApiDescriptionTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,4 +800,38 @@ public void testBinaryHasApiDescription() throws CoreException {
800800
IApiComponent componentA = profile.getApiComponent("component.a"); //$NON-NLS-1$
801801
assertTrue("Should have an .api_description file", componentA.hasApiDescription()); //$NON-NLS-1$
802802
}
803+
804+
/**
805+
* Tests that nested types with restrictions are persisted in XML.
806+
* This is a regression test for issue #1949 where nested classes marked
807+
* with @noreference were not being included in the .api_description file.
808+
*/
809+
@Test
810+
public void testNestedTypesWithRestrictionsPersisted() throws CoreException {
811+
// Create an API description with an outer class and a nested class with restrictions
812+
IApiDescription description = newDescription();
813+
814+
// Set package visibility to API
815+
description.setVisibility(Factory.packageDescriptor("test.pkg"), VisibilityModifiers.API); //$NON-NLS-1$
816+
817+
// Nested class with @noreference restriction
818+
IReferenceTypeDescriptor nestedType = Factory.typeDescriptor("test.pkg.OuterClass$NestedClass"); //$NON-NLS-1$
819+
description.setRestrictions(nestedType, RestrictionModifiers.NO_REFERENCE);
820+
821+
// Create component and generate XML
822+
IApiComponent component = TestSuiteHelper.createTestingApiComponent("test", "test", description); //$NON-NLS-1$ //$NON-NLS-2$
823+
Document xml = getApiDescriptionXML(component);
824+
String xmlString = Util.serializeDocument(xml);
825+
826+
// Verify the XML contains the nested type
827+
assertTrue("XML should contain nested type", xmlString.contains("OuterClass$NestedClass")); //$NON-NLS-1$ //$NON-NLS-2$
828+
829+
// Restore from XML and verify the restriction is preserved
830+
IApiDescription restored = new ApiDescription(null);
831+
ApiDescriptionProcessor.annotateApiSettings(null, restored, xmlString);
832+
833+
IApiAnnotations annotations = restored.resolveAnnotations(nestedType);
834+
assertEquals("Nested type should have NO_REFERENCE restriction", //$NON-NLS-1$
835+
RestrictionModifiers.NO_REFERENCE, annotations.getRestrictions());
836+
}
803837
}

apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiDescription.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,31 @@ protected boolean hasApiVisibility(ManifestNode node) {
179179
return false;
180180
}
181181

182+
/**
183+
* Returns whether this node or any of its descendants should be persisted
184+
* in the API description. A node should be persisted if it has API visibility
185+
* or if it (or any descendant) has restrictions.
186+
*
187+
* @return true if this node or any descendant should be persisted, false otherwise
188+
*/
189+
protected boolean shouldPersist() {
190+
// Persist if the node has API visibility
191+
if (hasApiVisibility(this)) {
192+
return true;
193+
}
194+
// Persist if the node has restrictions
195+
if (!RestrictionModifiers.isUnrestricted(this.restrictions)) {
196+
return true;
197+
}
198+
// Persist if any descendant has restrictions
199+
for (ManifestNode child : children.values()) {
200+
if (child.shouldPersist()) {
201+
return true;
202+
}
203+
}
204+
return false;
205+
}
206+
182207
/**
183208
* Ensure this node is up to date. Default implementation does nothing.
184209
* Subclasses should override as required.

apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ProjectApiDescription.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ protected ManifestNode refresh() {
121121

122122
@Override
123123
void persistXML(Document document, Element parentElement) {
124-
if (hasApiVisibility(this)) {
124+
if (shouldPersist()) {
125125
Element pkg = document.createElement(IApiXmlConstants.ELEMENT_PACKAGE);
126126
for (IPackageFragment fFragment : fFragments) {
127127
Element fragment = document.createElement(IApiXmlConstants.ELEMENT_PACKAGE_FRAGMENT);
@@ -302,7 +302,7 @@ private void logRefreshing() {
302302

303303
@Override
304304
void persistXML(Document document, Element parentElement) {
305-
if (hasApiVisibility(this)) {
305+
if (shouldPersist()) {
306306
Element type = document.createElement(IApiXmlConstants.ELEMENT_TYPE);
307307
type.setAttribute(IApiXmlConstants.ATTR_HANDLE, fType.getHandleIdentifier());
308308
persistAnnotations(type);

0 commit comments

Comments
 (0)