Skip to content

Commit

Permalink
Detect cyclic fragment references (#5229)
Browse files Browse the repository at this point in the history
* detect cyclic fragment references

* spelling

* move severity evaluation to the callsite

* update api

* UnknownDirectives are warnings

* fix circular fragments

* Update libraries/apollo-ast/src/commonMain/kotlin/com/apollographql/apollo3/ast/internal/ExecutableValidationScope.kt

Co-authored-by: Benoit Lubek <[email protected]>

* update test fixtures

---------

Co-authored-by: Benoit Lubek <[email protected]>
  • Loading branch information
martinbonnin and BoD authored Sep 19, 2023
1 parent abaae45 commit 8874b6b
Show file tree
Hide file tree
Showing 81 changed files with 1,239 additions and 624 deletions.
161 changes: 112 additions & 49 deletions libraries/apollo-ast/api/apollo-ast.api
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
public abstract interface class com/apollographql/apollo3/ast/ApolloIssue : com/apollographql/apollo3/ast/Issue {
}

public final class com/apollographql/apollo3/ast/ApolloParser {
public static final fun parseAsGQLDocument (Ljava/io/File;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
public static final fun parseAsGQLDocument (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;)Lcom/apollographql/apollo3/ast/GQLResult;
Expand Down Expand Up @@ -27,11 +30,48 @@ public final class com/apollographql/apollo3/ast/ApolloParser {
public static synthetic fun toGQLValue$default (Ljava/lang/String;Lcom/apollographql/apollo3/ast/ParserOptions;ILjava/lang/Object;)Lcom/apollographql/apollo3/ast/GQLValue;
}

public final class com/apollographql/apollo3/ast/ConditionalFragment : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/ConversionException : com/apollographql/apollo3/ast/SourceAwareException {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public synthetic fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
}

public final class com/apollographql/apollo3/ast/DeprecatedUsage : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/DifferentShape : com/apollographql/apollo3/ast/GraphQLValidationIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/DirectiveRedefinition : com/apollographql/apollo3/ast/GraphQLValidationIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public final fun getName ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/DuplicateDeferLabel : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/DuplicateTypeName : com/apollographql/apollo3/ast/GraphQLValidationIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/GQLArgument : com/apollographql/apollo3/ast/GQLNamed, com/apollographql/apollo3/ast/GQLNode {
public fun <init> (Lcom/apollographql/apollo3/ast/SourceLocation;Ljava/lang/String;Lcom/apollographql/apollo3/ast/GQLValue;)V
public synthetic fun <init> (Lcom/apollographql/apollo3/ast/SourceLocation;Ljava/lang/String;Lcom/apollographql/apollo3/ast/GQLValue;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down Expand Up @@ -751,8 +791,6 @@ public final class com/apollographql/apollo3/ast/GqlnodeKt {
public final class com/apollographql/apollo3/ast/GqloperationdefinitionKt {
public static final fun rootTypeDefinition (Lcom/apollographql/apollo3/ast/GQLOperationDefinition;Lcom/apollographql/apollo3/ast/Schema;)Lcom/apollographql/apollo3/ast/GQLTypeDefinition;
public static final fun validate (Lcom/apollographql/apollo3/ast/GQLOperationDefinition;Lcom/apollographql/apollo3/ast/Schema;Ljava/util/Map;)Ljava/util/List;
public static final fun validate (Lcom/apollographql/apollo3/ast/GQLOperationDefinition;Lcom/apollographql/apollo3/ast/Schema;Ljava/util/Map;Z)Ljava/util/List;
public static synthetic fun validate$default (Lcom/apollographql/apollo3/ast/GQLOperationDefinition;Lcom/apollographql/apollo3/ast/Schema;Ljava/util/Map;ZILjava/lang/Object;)Ljava/util/List;
}

public final class com/apollographql/apollo3/ast/GqlstringsKt {
Expand Down Expand Up @@ -780,77 +818,69 @@ public final class com/apollographql/apollo3/ast/GqlvalueKt {
public static final fun coerceInSchemaContextOrThrow (Lcom/apollographql/apollo3/ast/GQLValue;Lcom/apollographql/apollo3/ast/GQLType;Lcom/apollographql/apollo3/ast/Schema;)Lcom/apollographql/apollo3/ast/GQLValue;
}

public final class com/apollographql/apollo3/ast/InferredVariable {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/GQLType;)V
public final fun getName ()Ljava/lang/String;
public final fun getType ()Lcom/apollographql/apollo3/ast/GQLType;
}

public abstract class com/apollographql/apollo3/ast/Issue {
public synthetic fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;Lcom/apollographql/apollo3/ast/Issue$Severity;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getMessage ()Ljava/lang/String;
public final fun getSeverity ()Lcom/apollographql/apollo3/ast/Issue$Severity;
public final fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/Issue$ConditionalFragment : com/apollographql/apollo3/ast/Issue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public abstract interface class com/apollographql/apollo3/ast/GraphQLIssue : com/apollographql/apollo3/ast/Issue {
}

public final class com/apollographql/apollo3/ast/Issue$DeprecatedUsage : com/apollographql/apollo3/ast/Issue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public abstract interface class com/apollographql/apollo3/ast/GraphQLValidationIssue : com/apollographql/apollo3/ast/GraphQLIssue {
}

public final class com/apollographql/apollo3/ast/Issue$InlineFragmentWithoutTypeCondition : com/apollographql/apollo3/ast/Issue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
}

public final class com/apollographql/apollo3/ast/Issue$ParsingError : com/apollographql/apollo3/ast/Issue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public final class com/apollographql/apollo3/ast/InferredVariable {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/GQLType;)V
public final fun getName ()Ljava/lang/String;
public final fun getType ()Lcom/apollographql/apollo3/ast/GQLType;
}

public final class com/apollographql/apollo3/ast/Issue$ReservedEnumValueName : com/apollographql/apollo3/ast/Issue {
public final class com/apollographql/apollo3/ast/InlineFragmentWithoutTypeCondition : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/Issue$Severity : java/lang/Enum {
public static final field ERROR Lcom/apollographql/apollo3/ast/Issue$Severity;
public static final field WARNING Lcom/apollographql/apollo3/ast/Issue$Severity;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/apollographql/apollo3/ast/Issue$Severity;
public static fun values ()[Lcom/apollographql/apollo3/ast/Issue$Severity;
}

public final class com/apollographql/apollo3/ast/Issue$UnusedVariable : com/apollographql/apollo3/ast/Issue {
public final class com/apollographql/apollo3/ast/InvalidDeferDirective : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/Issue$UpperCaseField : com/apollographql/apollo3/ast/Issue {
public final class com/apollographql/apollo3/ast/InvalidDeferLabel : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/Issue$ValidationError : com/apollographql/apollo3/ast/Issue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;Lcom/apollographql/apollo3/ast/Issue$Severity;Lcom/apollographql/apollo3/ast/ValidationDetails;)V
public synthetic fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;Lcom/apollographql/apollo3/ast/Issue$Severity;Lcom/apollographql/apollo3/ast/ValidationDetails;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getDetails ()Lcom/apollographql/apollo3/ast/ValidationDetails;
public abstract interface class com/apollographql/apollo3/ast/Issue {
public abstract fun getMessage ()Ljava/lang/String;
public abstract fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/IssueKt {
public static final fun checkNoErrors (Ljava/util/List;)V
public static final fun containsError (Ljava/util/List;)Z
public static final fun checkEmpty (Ljava/util/List;)V
public static final fun checkValidGraphQL (Ljava/util/List;)V
}

public final class com/apollographql/apollo3/ast/MergeOptions$Companion {
public final fun getDefault ()Lcom/apollographql/apollo3/ast/MergeOptions;
}

public final class com/apollographql/apollo3/ast/NoQueryType : com/apollographql/apollo3/ast/GraphQLValidationIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/NodeContainer {
public fun <init> (Ljava/util/List;)V
public final fun assert ()V
public final fun getRemainingNodes ()Ljava/util/List;
public final fun setRemainingNodes (Ljava/util/List;)V
}

public final class com/apollographql/apollo3/ast/OtherValidationIssue : com/apollographql/apollo3/ast/GraphQLValidationIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/ParserOptions {
public static final field Companion Lcom/apollographql/apollo3/ast/ParserOptions$Companion;
public synthetic fun <init> (ZZZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down Expand Up @@ -881,11 +911,23 @@ public final class com/apollographql/apollo3/ast/ParserOptions$Companion {
public final fun getDefault ()Lcom/apollographql/apollo3/ast/ParserOptions;
}

public final class com/apollographql/apollo3/ast/ParsingError : com/apollographql/apollo3/ast/GraphQLIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/QueryDocumentMinifier {
public static final field INSTANCE Lcom/apollographql/apollo3/ast/QueryDocumentMinifier;
public static final fun minify (Ljava/lang/String;)Ljava/lang/String;
}

public final class com/apollographql/apollo3/ast/ReservedEnumValueName : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/Schema {
public static final field Companion Lcom/apollographql/apollo3/ast/Schema$Companion;
public static final field FIELD_POLICY Ljava/lang/String;
Expand Down Expand Up @@ -968,17 +1010,38 @@ public final class com/apollographql/apollo3/ast/TransformResult$Replace : com/a
public final fun getNewNode ()Lcom/apollographql/apollo3/ast/GQLNode;
}

public final class com/apollographql/apollo3/ast/UnknownDirective : com/apollographql/apollo3/ast/GraphQLValidationIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/UnrecognizedAntlrRule : com/apollographql/apollo3/ast/SourceAwareException {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
}

public final class com/apollographql/apollo3/ast/ValidationDetails : java/lang/Enum {
public static final field DuplicateTypeName Lcom/apollographql/apollo3/ast/ValidationDetails;
public static final field Other Lcom/apollographql/apollo3/ast/ValidationDetails;
public static final field UnknownDirective Lcom/apollographql/apollo3/ast/ValidationDetails;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/apollographql/apollo3/ast/ValidationDetails;
public static fun values ()[Lcom/apollographql/apollo3/ast/ValidationDetails;
public final class com/apollographql/apollo3/ast/UnusedFragment : com/apollographql/apollo3/ast/GraphQLValidationIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/UnusedVariable : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/UpperCaseField : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/VariableDeferLabel : com/apollographql/apollo3/ast/ApolloIssue {
public fun <init> (Ljava/lang/String;Lcom/apollographql/apollo3/ast/SourceLocation;)V
public fun getMessage ()Ljava/lang/String;
public fun getSourceLocation ()Lcom/apollographql/apollo3/ast/SourceLocation;
}

public final class com/apollographql/apollo3/ast/VariableUsage {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.apollographql.apollo3.ast

import com.apollographql.apollo3.annotations.ApolloDeprecatedSince


/**
* The result of a parsing or validation operation. It's tri-state:
*
Expand All @@ -11,15 +10,17 @@ import com.apollographql.apollo3.annotations.ApolloDeprecatedSince
* - value and issues => partial success
*
* - no value and no issues => not possible
*
* @property issues issues found during parsing/validations. Some of them might be Apollo specific and will not throw in [getOrThrow]
*/
class GQLResult<out V : Any>(
val value: V?,
val issues: List<Issue>,
) {

init {
check(value != null || issues.containsError()) {
"Apollo: GQLResult must contain a value or an error"
check(value != null || issues.isNotEmpty()) {
"Apollo: GQLResult must contain a value or issues"
}
}

Expand All @@ -30,10 +31,12 @@ class GQLResult<out V : Any>(
}

/**
* @throws SourceAwareException if there are validation errors
* @throws SourceAwareException if there are GraphQL errors
*
* [ApolloIssue] are ignored
*/
fun getOrThrow(): V {
issues.checkNoErrors()
issues.checkValidGraphQL()

check(value != null) {
"Apollo: no value and no error found"
Expand Down
Loading

0 comments on commit 8874b6b

Please sign in to comment.