Skip to content
Merged
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
89 changes: 69 additions & 20 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,82 @@
# Roadmap

## Overview
This is a high level roadmap predominantly for **v6**, **v7** and **v8**.
This is a high level roadmap for **v6**, **v7** and **v8** - what happens to the classic pipeline
and the new _Spec_ attributes and processing pipeline, and when.

In particular this is in relation to the introduction of the new _Spec_ attributes and processing pipeline and what may/will happen when.
The discussion and the tick list of what has shipped are in
[#1953](https://github.com/zircote/swagger-php/issues/1953). This file is the plan; the issue
tracks it.

## Deprecation rule
A `@deprecated` marker names the version that removes the thing:

```php
/** @deprecated since 6.11, removed in 8.0 - use ... instead */
```

Nothing is removed before the version its marker names, and nothing is removed without a marker.
Something marked for `8.0` keeps working through **v7** unchanged. That is what "no cliff" means
here: the marker is the promise.

## Timeline
### v6
`6.5.0` saw the introduction of the new `Spec` system. Right now this is considered not yet production ready.
The remainder of **v6** will be defined by improving and completing the new system.
`6.5.0` introduced the `Spec` system as opt-in beta. The remainder of **v6** is about completing
it and getting people onto it:

* `Spec` attributes declared frozen, and the **beta** label dropped in that minor
* a rector rule set for `OpenApi\Attributes` -> `OpenApi\Spec`
* a seam to contribute pre-built attributes to a `Specification` before resolution, for
framework integrations that do not scan
* docblock annotation support marked `@deprecated`, removed in `8.0` - the README has said so
since 4.8, the code now agrees, and parsing a docblock annotation triggers a runtime
deprecation once per run
* the relocation shims already marked (`Pipeline`, `SourceFinder`, `Analysers\TokenScanner`,
`Utils\TypeMapper`, `LegacyTypeResolver`) are removed in `7.0`
* `Generator::UNDEFINED` and `Generator::isDefault()` stay until `8.0` - every classic custom
processor uses them, so they go with classic and not before

Classic attributes, the `Generator` and the processors are **not** marked in v6. The replacement
is still beta for part of the major, and a stable API is not deprecated in favour of a beta one.

### v7
This is where things will start to turn:
* Default mode will switch to `hybrid` - this means existing `classic` projects should keep working via the bridge (probably with the exception of `NelmioApiDocBundle`, as that relies on a lot of actual `classic` features), although they will be routed through the new `spec` pipeline via a custom bridge.
* All classic code - annotations + attributes and related pipeline code will be marked `deprecated`
* All code marked `depecated` in **v6** will be removed
* Bridge is marked `deprecated`
* `Builder::setMode()` is marked `deprecated`
* `nikic/php-parser` is raised to `^5.0` — the `^4.19` branch parses no further than
This is where things turn:
* default mode switches to `hybrid` - existing `classic` projects keep working, routed through
the new pipeline via the bridge (probably with the exception of `NelmioApiDocBundle`, as that
relies on a lot of actual `classic` features)
* all classic code - annotations, attributes and the related pipeline code - is marked
`@deprecated`, removed in `8.0`
* the bridge and mode selection are marked `@deprecated`, removed in `8.0` - that is
`Builder::setMode()`, the `Builder\Mode` enum, `Console\GenerateInput::$mode` and the CLI's
`-m`/`--mode` option, which go together because there is one pipeline in `8.0` and nothing
left to select. These markers name no replacement, unlike every other marker here
* everything whose marker says `7.0` is removed
* `nikic/php-parser` is raised to `^5.0` - the `^4.19` branch parses no further than
PHP 8.3 syntax
## v8
`classic` is removed from the codebase, leaving only the spec pipeline. Annotations are no longer supported at all.

**Finding what to remove.** Code carries `@deprecated` from **v7**, which is the primary
marker and the one tooling understands. Documentation, fixture layout and test-matrix
structure cannot carry it — nothing consumes a docblock in a markdown file or a yaml
expectation — so those are marked inline with the mode they exist to serve: `[classic]`,
`[hybrid]`, or `[classic/hybrid]` for what serves both. `grep -rnE '\[(classic|hybrid)'`
lists them, and all of it goes when `classic` does.
* the v7 migration guide states the v8 namespace move below, so nobody meets it as a surprise

Open: whether the default **output** version follows the default mode. `classic` defaults to
OpenAPI 3.0.0 and `hybrid` to 3.1.0 today, so switching the default mode also switches the
default output version for everyone unless v7 pins 3.0.0. Decided in #1953 before v7.

### v8
`classic` is removed from the codebase, leaving only the spec pipeline. Annotations are no longer
supported at all.

The spec attributes move from `OpenApi\Spec` to `OpenApi\Attributes`. With one pipeline left,
"Spec" is a mode name that means nothing, and `OpenApi\Attributes` is the better home. For code
written against `OpenApi\Spec` that is one `use` line per file, and the rector set does it.

Open: whether `OpenApi\Spec` stays as deprecated aliases for one major, so the move is optional
until v9.

## Finding what to remove
Code carries `@deprecated` with the version that removes it, which is the primary marker and
the one tooling understands. Documentation, fixture layout and test-matrix structure cannot
carry it - nothing consumes a docblock in a markdown file or a yaml expectation - so those are
marked inline with the mode they exist to serve: `[classic]`, `[hybrid]`, or `[classic/hybrid]`
for what serves both. `grep -rnE '\[(classic|hybrid)'` lists them, and all of it goes when
`classic` does.

The marker names the mode rather than the release on purpose. A thing is `[hybrid]` for as
long as hybrid exists, which stays true whatever happens to this timeline; `[v8: drop]` would
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/modes.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,5 @@ The recommended migration path is:
::: tip Version timeline
- **v6** — spec/hybrid ship as opt-in beta. Classic remains default.
- **v7** — hybrid becomes the default mode. Classic still available. `setMode()` and all classic code deprecated.
- **v8** — classic removed. `setMode()` removed. Spec becomes default. Spec code might move to `OpenApi\Attributes`.
- **v8** — classic removed. `setMode()` removed. Spec becomes default. Spec attributes move to `OpenApi\Attributes`, one `use` line per file.
:::
24 changes: 24 additions & 0 deletions src/Analysers/DocBlockAnnotationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@
use OpenApi\Generator;
use OpenApi\GeneratorAwareTrait;

/**
* Builds annotations from docblock comments.
*
* @deprecated since 6.11, removed in 8.0 - use attributes instead
*/
class DocBlockAnnotationFactory implements AnnotationFactoryInterface
{
use GeneratorAwareTrait;

protected ?DocBlockParser $docBlockParser = null;

/** Reset per generator run, so a scan of a thousand annotated files reports once. */
protected bool $deprecationReported = false;

public function __construct(?DocBlockParser $docBlockParser = null)
{
$this->docBlockParser = $docBlockParser ?: new DocBlockParser();
Expand All @@ -30,6 +38,7 @@ public function isSupported(): bool
public function setGenerator(Generator $generator): static
{
$this->generator = $generator;
$this->deprecationReported = false;

$this->docBlockParser->setAliases($generator->getAliases());

Expand Down Expand Up @@ -60,6 +69,7 @@ public function build(\Reflector $reflector, Context $context): array
$annotations = [];
foreach ($this->docBlockParser->fromComment($comment, $context) as $instance) {
if ($instance instanceof OA\AbstractAnnotation) {
$this->reportDeprecation();
$annotations[] = $instance;
} else {
if ($context->is('other') === false) {
Expand All @@ -74,4 +84,18 @@ public function build(\Reflector $reflector, Context $context): array

return [];
}

/**
* Reported on the first docblock annotation actually parsed, not on the first docblock
* seen: a project that has migrated to attributes still has docblocks everywhere.
*/
protected function reportDeprecation(): void
{
if ($this->deprecationReported) {
return;
}

$this->deprecationReported = true;
trigger_deprecation('zircote/swagger-php', '6.11', 'Docblock annotations are deprecated and will be removed in 8.0; use attributes instead');
}
}
3 changes: 3 additions & 0 deletions src/Analysers/DocBlockParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
/**
* Extract swagger-php annotations from a [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) using Doctrine's DocParser.
*/
/**
* @deprecated since 6.11, removed in 8.0 - use attributes instead
*/
class DocBlockParser
{
protected DocParser $docParser;
Expand Down
2 changes: 1 addition & 1 deletion src/Analysers/TokenScanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace OpenApi\Analysers;

/**
* @deprecated use {@see \OpenApi\Utils\TokenScanner} instead
* @deprecated since 6.3.1, removed in 7.0 - use {@see \OpenApi\Utils\TokenScanner} instead
*/
class TokenScanner extends \OpenApi\Utils\TokenScanner
{
Expand Down
18 changes: 16 additions & 2 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
*/
class Generator
{
/** @deprecated Use {@see Undefined::UNDEFINED} instead. */
/** @deprecated since 6.3.1, removed in 8.0 - use {@see Undefined::UNDEFINED} instead */
public const UNDEFINED = Undefined::UNDEFINED;

/** @var array<string,string> */
Expand Down Expand Up @@ -77,7 +77,7 @@ public function __construct(?LoggerInterface $logger = null)
}

/**
* @deprecated use {@see Undefined::isDefault()} instead
* @deprecated since 6.3.1, removed in 8.0 - use {@see Undefined::isDefault()} instead
*
* @param mixed ...$value
*/
Expand All @@ -88,12 +88,17 @@ public static function isDefault(...$value): bool

/**
* @return array<string, string>
*
* @deprecated since 6.11, removed in 8.0 - docblock annotations only
*/
public function getAliases(): array
{
return $this->aliases;
}

/**
* @deprecated since 6.11, removed in 8.0 - docblock annotations only
*/
public function addAlias(string $alias, string $namespace): Generator
{
$this->aliases[$alias] = $namespace;
Expand All @@ -103,6 +108,8 @@ public function addAlias(string $alias, string $namespace): Generator

/**
* @param array<string, string> $aliases
*
* @deprecated since 6.11, removed in 8.0 - docblock annotations only
*/
public function setAliases(array $aliases): Generator
{
Expand All @@ -113,12 +120,17 @@ public function setAliases(array $aliases): Generator

/**
* @return list<string>|null
*
* @deprecated since 6.11, removed in 8.0 - docblock annotations only
*/
public function getNamespaces(): ?array
{
return $this->namespaces;
}

/**
* @deprecated since 6.11, removed in 8.0 - docblock annotations only
*/
public function addNamespace(string $namespace): Generator
{
$namespaces = (array) $this->getNamespaces();
Expand All @@ -129,6 +141,8 @@ public function addNamespace(string $namespace): Generator

/**
* @param list<string>|null $namespaces
*
* @deprecated since 6.11, removed in 8.0 - docblock annotations only
*/
public function setNamespaces(?array $namespaces): Generator
{
Expand Down
2 changes: 1 addition & 1 deletion src/Pipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace OpenApi;

/**
* @deprecated use {@see Utils\Pipeline} instead
* @deprecated since 6.3.1, removed in 7.0 - use {@see Utils\Pipeline} instead
*
* @extends Utils\Pipeline<mixed>
*/
Expand Down
2 changes: 1 addition & 1 deletion src/SourceFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace OpenApi;

/**
* @deprecated use {@see Utils\SourceFinder} instead
* @deprecated since 6.3.1, removed in 7.0 - use {@see Utils\SourceFinder} instead
*/
class SourceFinder extends Utils\SourceFinder
{
Expand Down
2 changes: 1 addition & 1 deletion src/Type/LegacyTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use OpenApi\Undefined;

/**
* @deprecated use `TypeInfoTypeResolver` instead
* @deprecated since 6.0.0, removed in 7.0 - use `TypeInfoTypeResolver` instead
*/
class LegacyTypeResolver extends AbstractTypeResolver
{
Expand Down
2 changes: 1 addition & 1 deletion src/TypeResolverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

interface TypeResolverInterface
{
/** @deprecated Use TypeMapper::NATIVE_TYPE_MAP instead */
/** @deprecated since 5.5.2, removed in 7.0 - use {@see TypeMapper::NATIVE_TYPE_MAP} instead */
public const NATIVE_TYPE_MAP = TypeMapper::NATIVE_TYPE_MAP;

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Utils/TypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use OpenApi\Type;

/**
* @deprecated use {@see Type\TypeMapper} instead
* @deprecated since 6.9.0, removed in 7.0 - use {@see Type\TypeMapper} instead
*/
class TypeMapper extends Type\TypeMapper
{
Expand Down
Loading