diff --git a/rules.go b/rules.go index c5be3f03..bd998124 100644 --- a/rules.go +++ b/rules.go @@ -203,43 +203,54 @@ func FieldsOnCorrectTypeRule(context *ValidationContext) *ValidationRuleInstance if node, ok := p.Node.(*ast.Field); ok { ttype := context.ParentType() - if ttype != nil { - fieldDef := context.FieldDef() - if fieldDef == nil { - // This isn't valid. Let's find suggestions, if any. - suggestedTypes := []string{} + if ttype == nil { + return action, result + } + if t, ok := ttype.(*Object); ok && t == nil { + return action, result + } + if t, ok := ttype.(*Interface); ok && t == nil { + return action, result + } + if t, ok := ttype.(*Union); ok && t == nil { + return action, result + } - nodeName := "" - if node.Name != nil { - nodeName = node.Name.Value - } + fieldDef := context.FieldDef() + if fieldDef == nil { + // This isn't valid. Let's find suggestions, if any. + suggestedTypes := []string{} + + nodeName := "" + if node.Name != nil { + nodeName = node.Name.Value + } - if ttype, ok := ttype.(Abstract); ok && IsAbstractType(ttype) { - siblingInterfaces := getSiblingInterfacesIncludingField(context.Schema(), ttype, nodeName) - implementations := getImplementationsIncludingField(context.Schema(), ttype, nodeName) - suggestedMaps := map[string]bool{} - for _, s := range siblingInterfaces { - if _, ok := suggestedMaps[s]; !ok { - suggestedMaps[s] = true - suggestedTypes = append(suggestedTypes, s) - } + if ttype, ok := ttype.(Abstract); ok && IsAbstractType(ttype) { + siblingInterfaces := getSiblingInterfacesIncludingField(context.Schema(), ttype, nodeName) + implementations := getImplementationsIncludingField(context.Schema(), ttype, nodeName) + suggestedMaps := map[string]bool{} + for _, s := range siblingInterfaces { + if _, ok := suggestedMaps[s]; !ok { + suggestedMaps[s] = true + suggestedTypes = append(suggestedTypes, s) } - for _, s := range implementations { - if _, ok := suggestedMaps[s]; !ok { - suggestedMaps[s] = true - suggestedTypes = append(suggestedTypes, s) - } + } + for _, s := range implementations { + if _, ok := suggestedMaps[s]; !ok { + suggestedMaps[s] = true + suggestedTypes = append(suggestedTypes, s) } } + } - message := UndefinedFieldMessage(nodeName, ttype.Name(), suggestedTypes) + message := UndefinedFieldMessage(nodeName, ttype.Name(), suggestedTypes) - reportError( - context, - message, - []ast.Node{node}, - ) - } + reportError( + context, + message, + []ast.Node{node}, + ) } } return action, result @@ -1073,10 +1084,10 @@ func collectFieldASTsAndDefs(context *ValidationContext, parentType Named, selec fieldName = selection.Name.Value } var fieldDef *FieldDefinition - if parentType, ok := parentType.(*Object); ok { + if parentType, ok := parentType.(*Object); ok && parentType != nil { fieldDef, _ = parentType.Fields()[fieldName] } - if parentType, ok := parentType.(*Interface); ok { + if parentType, ok := parentType.(*Interface); ok && parentType != nil { fieldDef, _ = parentType.Fields()[fieldName] } @@ -2119,6 +2130,9 @@ func VariablesInAllowedPositionRule(context *ValidationContext) *ValidationRuleI func isValidLiteralValue(ttype Input, valueAST ast.Value) (bool, []string) { // A value must be provided if the type is non-null. if ttype, ok := ttype.(*NonNull); ok { + if e := ttype.Error(); e != nil { + return false, []string{e.Error()} + } if valueAST == nil { if ttype.OfType.Name() != "" { return false, []string{fmt.Sprintf(`Expected "%v!", found null.`, ttype.OfType.Name())} diff --git a/rules_default_values_of_correct_type_test.go b/rules_default_values_of_correct_type_test.go index bc9545be..8457b388 100644 --- a/rules_default_values_of_correct_type_test.go +++ b/rules_default_values_of_correct_type_test.go @@ -101,3 +101,7 @@ func TestValidate_VariableDefaultValuesOfCorrectType_ListVariablesWithInvalidIte 2, 40), }) } + +func TestValidate_VariableDefaultValuesOfCorrectType_InvalidNonNull(t *testing.T) { + testutil.ExpectPassesRule(t, graphql.DefaultValuesOfCorrectTypeRule, `query($g:e!){a}`) +} diff --git a/rules_fields_on_correct_type_test.go b/rules_fields_on_correct_type_test.go index 294a0682..83dd194f 100644 --- a/rules_fields_on_correct_type_test.go +++ b/rules_fields_on_correct_type_test.go @@ -209,3 +209,7 @@ func TestValidate_FieldsOnCorrectTypeErrorMessage_WorksWithLotsOfSuggestions(t * t.Fatalf("Unexpected message, expected: %v, got %v", expected, message) } } + +func TestValidate_FieldsOnCorrectType_NilCrash(t *testing.T) { + testutil.ExpectPassesRule(t, graphql.FieldsOnCorrectTypeRule, `mutation{o}`) +} diff --git a/rules_overlapping_fields_can_be_merged_test.go b/rules_overlapping_fields_can_be_merged_test.go index b38b13a1..bd494883 100644 --- a/rules_overlapping_fields_can_be_merged_test.go +++ b/rules_overlapping_fields_can_be_merged_test.go @@ -729,3 +729,7 @@ func TestValidate_OverlappingFieldsCanBeMerged_ReturnTypesMustBeUnambiguous_Igno } `) } + +func TestValidate_OverlappingFieldsCanBeMerged_NilCrash(t *testing.T) { + testutil.ExpectPassesRule(t, graphql.OverlappingFieldsCanBeMergedRule, `subscription {e}`) +} diff --git a/type_info.go b/type_info.go index 39838295..bcdc84a8 100644 --- a/type_info.go +++ b/type_info.go @@ -252,14 +252,14 @@ func DefaultTypeInfoFieldDef(schema *Schema, parentType Type, fieldAST *ast.Fiel schema.QueryType() == parentType { return TypeMetaFieldDef } - if name == TypeNameMetaFieldDef.Name { - if _, ok := parentType.(*Object); ok && parentType != nil { + if name == TypeNameMetaFieldDef.Name && parentType != nil { + if t, ok := parentType.(*Object); ok && t != nil { return TypeNameMetaFieldDef } - if _, ok := parentType.(*Interface); ok && parentType != nil { + if t, ok := parentType.(*Interface); ok && t != nil { return TypeNameMetaFieldDef } - if _, ok := parentType.(*Union); ok && parentType != nil { + if t, ok := parentType.(*Union); ok && t != nil { return TypeNameMetaFieldDef } }