Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 256 additions & 0 deletions IMPLEMENTATION_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
# .apiconfig Feature Implementation Summary

## Overview

This implementation adds support for a `.apiconfig` file that allows projects to configure API Tools version increment rules and error handling. This addresses the need for project-level configuration that can be shared via version control.

## Files Added

### Core Implementation

1. **ApiConfigSettings.java** - Data structure holding configuration
- `VersionSegment` enum: MAJOR, MINOR, MICRO
- `ErrorMode` enum: ERROR, WARNING, IGNORE, FILTER
- `VersionIncrementRule` class: Defines which segment to increment and by how much
- Settings for major, minor, and micro version rules

2. **ApiConfigParser.java** - Parser for .apiconfig files
- Supports key=value format with comments
- Parses version increment rules (e.g., "major.version.increment = minor+1")
- Parses error modes (e.g., "major.version.error = filter")
- Can parse from IProject, File, or InputStream

3. **IApiCoreConstants.java** (modified)
- Added `API_CONFIG_FILE_NAME = ".apiconfig"` constant

### Integration

4. **BaseApiAnalyzer.java** (modified)
- Added `fApiConfigSettings` field to store loaded configuration
- Added `loadApiConfigSettings()` method to load config from project
- Added `calculateNewVersion()` method to compute version increments using config
- Added `handleVersionProblem()` method to handle problems per error mode
- Added `getErrorModeForProblemKind()` to map problem types to error modes
- Added `createAutoGeneratedFilter()` to auto-generate filters when error mode is FILTER
- Modified all version increment calculations to use `calculateNewVersion()`
- Modified version problem handling to check error mode

### Tests

5. **ApiConfigParserTests.java** - Unit tests for parser
- Tests empty config, comments, whitespace handling
- Tests version increment parsing
- Tests error mode parsing
- Tests complete configurations

6. **ApiConfigVersionTests.java** - Integration tests
- Tests default settings
- Tests custom increments
- Tests error modes
- Tests constant definition

7. **ApiToolsTestSuite.java** (modified)
- Added ApiConfigParserTests to test suite

### Documentation

8. **APICONFIG.md** - Comprehensive user documentation
- File format specification
- Configuration options
- Use cases and examples
- Migration guide
- Troubleshooting

9. **.apiconfig.example** - Example configuration file
- Shows Eclipse Platform pattern
- Documents all configuration options
- Can be copied and customized

## Key Features Implemented

### 1. Custom Version Increment Rules

Users can configure how each semantic change level (major, minor, micro) should increment versions:

```properties
# Instead of major+1, increment minor by 1
major.version.increment = minor+1

# Standard minor increment
minor.version.increment = minor+1

# Increment micro by 100 instead of 1
micro.version.increment = micro+100
```

### 2. Error Handling Modes

Users can control how version problems are reported:

```properties
# Auto-generate filters for major version issues
major.version.error = filter

# Report minor issues as errors (default)
minor.version.error = error

# Report micro issues as warnings
micro.version.error = warning

# Or ignore completely
# micro.version.error = ignore
```

### 3. Automatic Filter Generation

When `error = filter` is configured, the system automatically:
1. Creates an ApiProblemFilter for the issue
2. Adds an explanatory comment (e.g., "Suppressed by .apiconfig: Breaking changes detected: ...")
3. Adds the filter to the project's .api_filters file

### 4. Project-Level Configuration

The `.apiconfig` file is discovered hierarchically like `.gitignore` or `.editorconfig`:
- Placed in project root
- Committed to version control
- Shared across all developers
- No IDE-specific configuration needed

## Design Decisions

### 1. Simple File Format

Chose properties-style format (key=value) for simplicity and familiarity:
- Easy to hand-edit
- No XML overhead
- Supports comments with #
- Similar to .editorconfig

### 2. Segment-Based Configuration

Configuration is organized by semantic change level (major/minor/micro):
- Intuitive for understanding impact
- Aligns with OSGi versioning semantics
- Allows different rules for different change types

### 3. Conservative Defaults

When no `.apiconfig` exists:
- Falls back to standard behavior (each segment increments by 1)
- No breaking changes to existing projects
- Opt-in configuration

### 4. Error Mode as Optional Enhancement

The error mode feature (especially FILTER) is optional:
- Basic version increment customization works without it
- FILTER mode provides automation for common workflows
- Other modes (WARNING, IGNORE) provide flexibility

### 5. Integration Point

Integrated at BaseApiAnalyzer level:
- Central point where all version problems are created
- Can intercept problems before they're reported
- Has access to project context for loading config

## Testing Strategy

### Unit Tests (ApiConfigParserTests)
- Test file parsing in isolation
- Test various input formats
- Test error handling

### Integration Tests (ApiConfigVersionTests)
- Test data structure behavior
- Test configuration of settings
- Test interaction with constants

### Manual Testing Needed
Full integration testing with actual projects would require:
- Setting up baseline comparisons
- Creating projects with API changes
- Verifying version suggestions use config
- Verifying filters are auto-generated

## Limitations and Future Work

### Current Limitations

1. **Error mode granularity**: Error modes apply to all problems of a type (e.g., all MAJOR problems), not specific scenarios

2. **No validation**: The parser accepts any increment amount - very large increments might be confusing

3. **Filter comment format**: Auto-generated filter comments are simple - could be enhanced with more detail

4. **No UI integration**: Configuration must be done by editing text file - no IDE UI provided

### Possible Future Enhancements

1. **IDE UI**: Add preference page to edit .apiconfig visually

2. **Per-package configuration**: Allow different rules for different packages

3. **Validation**: Warn about unusual increment amounts or configurations

4. **Quick fixes**: Provide quick fixes to create/update .apiconfig when problems occur

5. **Templates**: Provide .apiconfig templates for common patterns (Eclipse, Apache, etc.)

6. **Format validation**: Provide validation of .apiconfig syntax with error markers

## API Compatibility

This implementation maintains full backward compatibility:

- No changes to existing APIs
- All new classes in internal packages
- No changes to serialization formats
- Existing .api_filters files continue to work
- Projects without .apiconfig work as before

## Performance Considerations

Minimal performance impact:

- Config loaded once per analysis run (cached in field)
- Simple properties parsing (no XML, no complex formats)
- No additional file I/O beyond initial load
- Filter generation only when FILTER mode is used

## Use Cases Addressed

### Eclipse Platform Pattern
Eclipse Platform doesn't use major version increments. Configuration:
```properties
major.version.increment = minor+1
major.version.error = filter
```

### Service Release Pattern
Projects that increment micro by 100:
```properties
micro.version.increment = micro+100
```

### Development Projects
Projects wanting lenient warnings:
```properties
major.version.error = warning
minor.version.error = warning
```

## Summary

This implementation provides a flexible, project-level configuration mechanism for API Tools version management. It addresses the original requirements:

✅ Support `.apiconfig` file in project root
✅ Configure version increment rules per segment
✅ Support redirecting increments (e.g., major → minor)
✅ Support custom increment amounts (e.g., micro+100)
✅ Provide error mode configuration
✅ Auto-generate filters when error mode is "filter"
✅ Maintain backward compatibility
✅ Include tests and documentation

The implementation is minimal, focused, and provides a solid foundation for future enhancements.
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*******************************************************************************
* Copyright (c) 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.api.tools.builder.tests.compatibility;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.pde.api.tools.internal.ApiConfigParser;
import org.eclipse.pde.api.tools.internal.ApiConfigSettings;
import org.eclipse.pde.api.tools.internal.IApiCoreConstants;

import junit.framework.TestCase;

/**
* Tests for .apiconfig file integration with version checking
*/
public class ApiConfigVersionTests extends TestCase {

public ApiConfigVersionTests(String name) {
super(name);
}

/**
* Test that ApiConfigSettings can be created and have correct defaults
*/
public void testDefaultSettings() {
ApiConfigSettings settings = new ApiConfigSettings();

assertNotNull("Settings should not be null", settings);
assertEquals("Default major increment should be MAJOR+1",
ApiConfigSettings.VersionSegment.MAJOR,
settings.getMajorVersionIncrement().getTargetSegment());
assertEquals("Default major increment amount should be 1",
1,
settings.getMajorVersionIncrement().getIncrementAmount());

assertEquals("Default minor increment should be MINOR+1",
ApiConfigSettings.VersionSegment.MINOR,
settings.getMinorVersionIncrement().getTargetSegment());
assertEquals("Default minor increment amount should be 1",
1,
settings.getMinorVersionIncrement().getIncrementAmount());

assertEquals("Default micro increment should be MICRO+1",
ApiConfigSettings.VersionSegment.MICRO,
settings.getMicroVersionIncrement().getTargetSegment());
assertEquals("Default micro increment amount should be 1",
1,
settings.getMicroVersionIncrement().getIncrementAmount());
}

/**
* Test that ApiConfigSettings can be configured with custom increments
*/
public void testCustomIncrements() {
ApiConfigSettings settings = new ApiConfigSettings();

// Configure major to increment minor instead (like Eclipse Platform)
ApiConfigSettings.VersionIncrementRule majorRule =
new ApiConfigSettings.VersionIncrementRule(ApiConfigSettings.VersionSegment.MINOR, 1);
settings.setMajorVersionIncrement(majorRule);

// Configure micro to increment by 100
ApiConfigSettings.VersionIncrementRule microRule =
new ApiConfigSettings.VersionIncrementRule(ApiConfigSettings.VersionSegment.MICRO, 100);
settings.setMicroVersionIncrement(microRule);

assertEquals("Major should increment MINOR+1",
ApiConfigSettings.VersionSegment.MINOR,
settings.getMajorVersionIncrement().getTargetSegment());

assertEquals("Micro should increment MICRO+100",
100,
settings.getMicroVersionIncrement().getIncrementAmount());
}

/**
* Test that error modes can be configured
*/
public void testErrorModes() {
ApiConfigSettings settings = new ApiConfigSettings();

settings.setMajorVersionError(ApiConfigSettings.ErrorMode.FILTER);
settings.setMinorVersionError(ApiConfigSettings.ErrorMode.WARNING);
settings.setMicroVersionError(ApiConfigSettings.ErrorMode.IGNORE);

assertEquals("Major error mode should be FILTER",
ApiConfigSettings.ErrorMode.FILTER,
settings.getMajorVersionError());
assertEquals("Minor error mode should be WARNING",
ApiConfigSettings.ErrorMode.WARNING,
settings.getMinorVersionError());
assertEquals("Micro error mode should be IGNORE",
ApiConfigSettings.ErrorMode.IGNORE,
settings.getMicroVersionError());
}

/**
* Test that .apiconfig constant is defined
*/
public void testApiConfigConstant() {
assertNotNull("API_CONFIG_FILE_NAME constant should be defined",
IApiCoreConstants.API_CONFIG_FILE_NAME);
assertEquals(".apiconfig file name should be correct",
".apiconfig",
IApiCoreConstants.API_CONFIG_FILE_NAME);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.eclipse.pde.api.tools.search.tests.SearchEngineTests;
import org.eclipse.pde.api.tools.search.tests.SkippedComponentTests;
import org.eclipse.pde.api.tools.search.tests.UseSearchTests;
import org.eclipse.pde.api.tools.util.tests.ApiConfigParserTests;
import org.eclipse.pde.api.tools.util.tests.HeadlessApiBaselineManagerTests;
import org.eclipse.pde.api.tools.util.tests.SignaturesTests;
import org.eclipse.pde.api.tools.util.tests.TarEntryTests;
Expand Down Expand Up @@ -64,7 +65,8 @@
ApiProblemFactoryTests.class, ApiFilterTests.class, TarEntryTests.class, TarExceptionTests.class,
OSGiLessAnalysisTests.class, ApiModelCacheTests.class, BadClassfileTests.class,
CRCTests.class,
AllDeltaTests.class
AllDeltaTests.class,
ApiConfigParserTests.class
})
public class ApiToolsTestSuite {

Expand Down
Loading
Loading