Skip to content

Commit

Permalink
Merge pull request #196 from nextcloud/feat/generate-spec/disallow-un…
Browse files Browse the repository at this point in the history
…used-schemas

feat(generate-spec): Disallow unused schemas
  • Loading branch information
provokateurin authored Dec 17, 2024
2 parents 40302d1 + 86dfdc3 commit a644eac
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 8 deletions.
24 changes: 16 additions & 8 deletions generate-spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,8 @@
}
}

$usedSchemas = ['Capabilities', 'PublicCapabilities'];

foreach ($scopePaths as $scope => $paths) {
$openapiScope = $openapi;

Expand All @@ -955,29 +957,29 @@
$openapiScope['paths'] = array_merge(...$fullScopePathArrays);
$openapiScope['components']['schemas'] = $schemas;
} else {
$usedSchemas = [];
$usedRefs = [];
foreach ($paths as $urlRoutes) {
foreach ($urlRoutes as $routeData) {
foreach ($routeData['responses'] as $responseData) {
if (isset($responseData['content']) && $responseData['content'] !== []) {
$usedSchemas[] = Helpers::collectUsedRefs($responseData['content']);
$usedRefs[] = Helpers::collectUsedRefs($responseData['content']);
}
}
if (isset($routeData['requestBody']['content']) && $routeData['requestBody']['content'] !== []) {
$usedSchemas[] = Helpers::collectUsedRefs($routeData['requestBody']['content']);
$usedRefs[] = Helpers::collectUsedRefs($routeData['requestBody']['content']);
}
}
}

$usedSchemas = array_merge(...$usedSchemas);
$usedRefs = array_merge(...$usedRefs);

$scopedSchemas = [];
while ($usedSchema = array_shift($usedSchemas)) {
if (!str_starts_with((string)$usedSchema, '#/components/schemas/')) {
while ($usedRef = array_shift($usedRefs)) {
if (!str_starts_with((string)$usedRef, '#/components/schemas/')) {
continue;
}

$schemaName = substr((string)$usedSchema, strlen('#/components/schemas/'));
$schemaName = substr((string)$usedRef, strlen('#/components/schemas/'));

if (!isset($schemas[$schemaName])) {
Logger::error('app', "Schema $schemaName used by scope $scope is not defined");
Expand All @@ -986,11 +988,12 @@
$newRefs = Helpers::collectUsedRefs($schemas[$schemaName]);
foreach ($newRefs as $newRef) {
if (!isset($scopedSchemas[substr((string)$newRef, strlen('#/components/schemas/'))])) {
$usedSchemas[] = $newRef;
$usedRefs[] = $newRef;
}
}

$scopedSchemas[$schemaName] = $schemas[$schemaName];
$usedSchemas[] = $schemaName;
}

if (isset($schemas['Capabilities'])) {
Expand Down Expand Up @@ -1031,6 +1034,11 @@
Logger::info('app', 'Generated scope ' . $scope . ' with ' . $pathsCount . ' routes!');
}

$unusedSchemas = array_diff(array_keys($schemas), $usedSchemas);
if ($unusedSchemas !== []) {
Logger::error('app', 'Unused schemas: ' . implode(', ', $unusedSchemas));
}

if (Logger::$errorCount > 0) {
Logger::panic('app', 'Encountered ' . Logger::$errorCount . ' errors that need to be fixed!');
}
21 changes: 21 additions & 0 deletions tests/lib/Capabilities.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Notifications;

use OCP\Capabilities\ICapability;

class Capabilities implements ICapability {
/**
* @return array{test: array{a: int}}
*/
public function getCapabilities(): array {
return [];
}
}
21 changes: 21 additions & 0 deletions tests/lib/PublicCapabilities.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Notifications;

use OCP\Capabilities\IPublicCapability;

class PublicCapabilities implements IPublicCapability {
/**
* @return array{test: array{b: string}}
*/
public function getCapabilities(): array {
return [];
}
}
39 changes: 39 additions & 0 deletions tests/openapi-administration.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@
}
},
"schemas": {
"Capabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "integer",
"format": "int64"
}
}
}
}
},
"OCSMeta": {
"type": "object",
"required": [
Expand All @@ -44,6 +64,25 @@
}
}
},
"PublicCapabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"b"
],
"properties": {
"b": {
"type": "string"
}
}
}
}
},
"PushDevice": {
"allOf": [
{
Expand Down
39 changes: 39 additions & 0 deletions tests/openapi-ex_app.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@
}
},
"schemas": {
"Capabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "integer",
"format": "int64"
}
}
}
}
},
"OCSMeta": {
"type": "object",
"required": [
Expand All @@ -43,6 +63,25 @@
"type": "string"
}
}
},
"PublicCapabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"b"
],
"properties": {
"b": {
"type": "string"
}
}
}
}
}
}
},
Expand Down
39 changes: 39 additions & 0 deletions tests/openapi-federation.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@
}
},
"schemas": {
"Capabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "integer",
"format": "int64"
}
}
}
}
},
"OCSMeta": {
"type": "object",
"required": [
Expand All @@ -43,6 +63,25 @@
"type": "string"
}
}
},
"PublicCapabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"b"
],
"properties": {
"b": {
"type": "string"
}
}
}
}
}
}
},
Expand Down
39 changes: 39 additions & 0 deletions tests/openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@
}
},
"schemas": {
"Capabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "integer",
"format": "int64"
}
}
}
}
},
"Collection": {
"type": "array",
"items": {
Expand Down Expand Up @@ -179,6 +199,25 @@
}
}
},
"PublicCapabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"b"
],
"properties": {
"b": {
"type": "string"
}
}
}
}
},
"PushDevice": {
"allOf": [
{
Expand Down
39 changes: 39 additions & 0 deletions tests/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@
}
},
"schemas": {
"Capabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"a"
],
"properties": {
"a": {
"type": "integer",
"format": "int64"
}
}
}
}
},
"Collection": {
"type": "array",
"items": {
Expand Down Expand Up @@ -179,6 +199,25 @@
}
}
},
"PublicCapabilities": {
"type": "object",
"required": [
"test"
],
"properties": {
"test": {
"type": "object",
"required": [
"b"
],
"properties": {
"b": {
"type": "string"
}
}
}
}
},
"RequestProperty": {
"type": "object",
"required": [
Expand Down

0 comments on commit a644eac

Please sign in to comment.