Skip to content

Commit e131072

Browse files
Merge pull request #3 from zetcco/add_deprecated_support
Add `@deprecated` directive support
2 parents d757626 + 9ea2d1d commit e131072

File tree

8 files changed

+207
-3
lines changed

8 files changed

+207
-3
lines changed

ballerina/Dependencies.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
[ballerina]
77
dependencies-toml-version = "2"
8-
distribution-version = "2201.8.0"
8+
distribution-version = "2201.8.4"
99

1010
[[package]]
1111
org = "ballerina"
@@ -93,7 +93,7 @@ modules = [
9393
[[package]]
9494
org = "ballerina"
9595
name = "http"
96-
version = "2.10.5"
96+
version = "2.10.6"
9797
dependencies = [
9898
{org = "ballerina", name = "auth"},
9999
{org = "ballerina", name = "cache"},

ballerina/modules/merger/merge_result_types.bal

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ type DescriptionMergeResult record {|
4040
string? result;
4141
|};
4242

43+
type DeprecationMergeResult record {|
44+
*MergeResult;
45+
boolean isDeprecated;
46+
string? deprecationReason = ();
47+
|};
48+
4349
type DefaultValueMergeResult record {|
4450
*MergeResult;
4551
anydata? result;

ballerina/modules/merger/merger.bal

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ public class Merger {
614614
}
615615

616616
DescriptionMergeResult mergedDesc = self.mergeDescription(descriptionSources);
617-
// Handle deprecations
617+
DeprecationMergeResult mergedDeprecation = self.mergeDeprecations(deprecationSources);
618618

619619
parser:__EnumValue mergedEnumValue = {
620620
name: valueName,
@@ -623,6 +623,12 @@ public class Merger {
623623

624624
check self.applyJoinEnumDirective(mergedEnumValue, definingSubgraphs);
625625

626+
if mergedDeprecation.isDeprecated {
627+
mergedEnumValue.isDeprecated = mergedDeprecation.isDeprecated;
628+
mergedEnumValue.deprecationReason = mergedDeprecation.deprecationReason;
629+
check self.applyDeprecatedDirective(mergedEnumValue.appliedDirectives, mergedDeprecation.deprecationReason);
630+
}
631+
626632
mergedEnumValues.push(mergedEnumValue);
627633
}
628634

@@ -765,6 +771,16 @@ public class Merger {
765771
outputTypeMismatches = typeMergeResult.sources
766772
);
767773

774+
DeprecationMergeResult mergedDeprecation = self.mergeDeprecations(deprecationSources);
775+
if mergedDeprecation.isDeprecated {
776+
mergedField.isDeprecated = mergedDeprecation.isDeprecated;
777+
mergedField.deprecationReason = mergedDeprecation.deprecationReason;
778+
check self.applyDeprecatedDirective(
779+
mergedField.appliedDirectives,
780+
mergedDeprecation.deprecationReason
781+
);
782+
}
783+
768784
mergedFields[mergedField.name] = mergedField;
769785

770786
}
@@ -1138,6 +1154,16 @@ public class Merger {
11381154

11391155
}
11401156

1157+
isolated function mergeDeprecations(DeprecationSource[] sources) returns DeprecationMergeResult {
1158+
Hint[] hints = [];
1159+
foreach DeprecationSource 'source in sources {
1160+
if 'source.definition[0] {
1161+
return { hints, isDeprecated: 'source.definition[0], deprecationReason: 'source.definition[1] };
1162+
}
1163+
}
1164+
return { hints, isDeprecated: false };
1165+
}
1166+
11411167
isolated function getMergedOutputTypeReference(parser:__Type typeA, parser:__Type typeB) returns parser:__Type|InternalError|MergeError {
11421168
parser:__Type? typeAWrappedType = typeA.ofType;
11431169
parser:__Type? typeBWrappedType = typeB.ofType;
@@ -1355,6 +1381,17 @@ public class Merger {
13551381
);
13561382
}
13571383

1384+
isolated function applyDeprecatedDirective(parser:__AppliedDirective[] appliedDirs, string? reason) returns InternalError? {
1385+
appliedDirs.push(
1386+
check self.getAppliedDirectiveFromName(
1387+
parser:DEPRECATED_DIR,
1388+
{
1389+
reason
1390+
}
1391+
)
1392+
);
1393+
}
1394+
13581395
// Filter out the Subgraphs which defines the given typeName
13591396
isolated function getDefiningSubgraphs(string typeName) returns Subgraph[] {
13601397
Subgraph[] subgraphs = [];
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com) All Rights Reserved.
2+
//
3+
// WSO2 LLC. licenses this file to you under the Apache License,
4+
// Version 2.0 (the "License"); you may not use this file except
5+
// in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing,
11+
// software distributed under the License is distributed on an
12+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13+
// KIND, either express or implied. See the License for the
14+
// specific language governing permissions and limitations
15+
// under the License.
16+
17+
import ballerina/test;
18+
import graphql_schema_registry.parser;
19+
20+
@test:Config {
21+
groups: ["merger", "compatible", "deprecated"],
22+
dataProvider: dataProviderDeprecatedDirective
23+
}
24+
function testDeprecatedDirective(TestSchemas schemas, string typeName) returns error? {
25+
parser:__Type actualType = schemas.merged.types.get(typeName);
26+
parser:__Type expectedType = schemas.parsed.types.get(typeName);
27+
28+
test:assertEquals(actualType, expectedType);
29+
}
30+
31+
function dataProviderDeprecatedDirective() returns [TestSchemas, string][]|error {
32+
TestSchemas schemas = check getMergedAndParsedSchemas("deprecated_directive");
33+
34+
return [
35+
[ schemas, "Query" ],
36+
[ schemas, "Status" ],
37+
[ schemas, "IntersectedEnum" ]
38+
];
39+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
schema
2+
@link(url: "https://specs.apollo.dev/link/v1.0")
3+
@link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION)
4+
{
5+
query: Query
6+
}
7+
8+
directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE
9+
10+
directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
11+
12+
directive @join__graph(name: String!, url: String!) on ENUM_VALUE
13+
14+
directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
15+
16+
directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false, resolvable: Boolean! = true, isInterfaceObject: Boolean! = false) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
17+
18+
directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION
19+
20+
directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA
21+
22+
enum IntersectedEnum
23+
@join__type(graph: SUBG1)
24+
@join__type(graph: SUBG2)
25+
{
26+
FOO @join__enumValue(graph: SUBG1) @join__enumValue(graph: SUBG2)
27+
BAR @join__enumValue(graph: SUBG1) @join__enumValue(graph: SUBG2)
28+
BUX @join__enumValue(graph: SUBG1) @join__enumValue(graph: SUBG2)
29+
}
30+
31+
scalar join__FieldSet
32+
33+
enum join__Graph {
34+
SUBG1 @join__graph(name: "subg1", url: "http://subg1")
35+
SUBG2 @join__graph(name: "subg2", url: "http://subg2")
36+
}
37+
38+
scalar link__Import
39+
40+
enum link__Purpose {
41+
"""
42+
`SECURITY` features provide metadata necessary to securely resolve fields.
43+
"""
44+
SECURITY
45+
46+
"""
47+
`EXECUTION` features provide metadata necessary for operation execution.
48+
"""
49+
EXECUTION
50+
}
51+
52+
type Query
53+
@join__type(graph: SUBG1)
54+
@join__type(graph: SUBG2)
55+
{
56+
dep_name: String @join__field(graph: SUBG1)
57+
toBeRemoved: Int @join__field(graph: SUBG1) @deprecated(reason: "Will be removed in the future")
58+
inputEnum(enum: IntersectedEnum): String @join__field(graph: SUBG1)
59+
shareableDeprecated: String @deprecated(reason: "First subgraph")
60+
dep_foo: String @join__field(graph: SUBG2)
61+
}
62+
63+
enum Status
64+
@join__type(graph: SUBG1)
65+
@join__type(graph: SUBG2)
66+
{
67+
COMPLETED @join__enumValue(graph: SUBG1) @join__enumValue(graph: SUBG2)
68+
FINISHED @join__enumValue(graph: SUBG1) @join__enumValue(graph: SUBG2) @deprecated
69+
IN_PROGRESS @join__enumValue(graph: SUBG1) @join__enumValue(graph: SUBG2) @deprecated
70+
FAILED @join__enumValue(graph: SUBG1) @join__enumValue(graph: SUBG2) @deprecated
71+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@shareable"])
2+
3+
type Query {
4+
dep_name: String
5+
toBeRemoved: Int @deprecated(reason: "Will be removed in the future")
6+
inputEnum(enum: IntersectedEnum): String
7+
shareableDeprecated: String @deprecated(reason: "First subgraph") @shareable
8+
}
9+
10+
enum Status {
11+
COMPLETED
12+
FINISHED @deprecated
13+
IN_PROGRESS
14+
FAILED @deprecated
15+
}
16+
17+
enum IntersectedEnum {
18+
FOO
19+
BAR
20+
BUX
21+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@shareable"])
2+
3+
type Query {
4+
dep_foo: String
5+
shareableDeprecated: String @deprecated(reason: "Second subgraph") @shareable
6+
}
7+
8+
enum Status {
9+
COMPLETED
10+
FINISHED
11+
IN_PROGRESS @deprecated
12+
FAILED @deprecated
13+
}
14+
15+
enum IntersectedEnum {
16+
FOO
17+
BAR
18+
BUX
19+
NOT_INCLUDED_IN_ENUM_INTERSECTION @deprecated
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
federation_version: =2.5.3
2+
subgraphs:
3+
subg1:
4+
routing_url: http://subg1
5+
schema:
6+
file: ./subg1.graphql
7+
subg2:
8+
routing_url: http://subg2
9+
schema:
10+
file: ./subg2.graphql

0 commit comments

Comments
 (0)