public override void Analyze( IDocumentAnalyzerContext context, OperationDefinitionNode operation, FieldNode fieldSelection, PossibleSelections possibleSelections, IType fieldType, InterfaceType namedType, Path path) { IFragmentNode returnTypeFragment = ResolveReturnType( namedType, fieldSelection, possibleSelections.ReturnType); ComplexOutputTypeModel returnType = CreateInterfaceModel( context, returnTypeFragment, path); CreateClassModels( context, operation, fieldSelection, possibleSelections, returnTypeFragment, returnType, fieldType, path); }
private static void RegisterOperationModel( IDocumentAnalyzerContext context, DocumentNode document, OperationDefinitionNode operationDefinition) { ComplexOutputTypeModel returnType = context.Types.OfType <ComplexOutputTypeModel>() .First(t => t.SelectionSet == operationDefinition.SelectionSet && t.IsInterface); var parser = new ParserModel( context.GetOrCreateName( GetClassName(operationDefinition.Name !.Value, "ResultParser")), operationDefinition, returnType, context.FieldParsers.Where(t => t.Operation == operationDefinition).ToList()); var operation = new OperationModel( returnType.Name, context.Schema.GetOperationType(operationDefinition.Operation), document, operationDefinition, parser, CreateOperationArguments(context, operationDefinition)); context.Register(operation); }
private void CreateClassModels( IDocumentAnalyzerContext context, OperationDefinitionNode operation, FieldNode fieldSelection, PossibleSelections possibleSelections, ComplexOutputTypeModel returnType, IType fieldType, Path path) { IReadOnlyCollection <SelectionInfo> selections = possibleSelections.Variants; IReadOnlyList <ComplexOutputTypeModel> modelTypes = CreateClassModels( context, returnType, fieldSelection, selections, path); CreateFieldParserModel( context, operation, fieldSelection, path, returnType, fieldType, modelTypes); }
private IReadOnlyList <ComplexOutputTypeModel> CreateChildInterfaceModels( IDocumentAnalyzerContext context, IFragmentNode fragmentNode, Path path, Stack <ISet <string> > levels, ISet <string> implementedFields) { if (fragmentNode.Children.Count == 0) { return(Array.Empty <ComplexOutputTypeModel>()); } var implementedByChildren = new HashSet <string>(); levels.Push(implementedByChildren); var implements = new List <ComplexOutputTypeModel>(); foreach (IFragmentNode child in fragmentNode.Children) { implements.Add(CreateInterfaceModel(context, child, path, levels)); } levels.Pop(); foreach (string fieldName in implementedByChildren) { implementedFields.Add(fieldName); } return(implements); }
public OutputTypeModel AnalyzeOperation( IDocumentAnalyzerContext context, SelectionSetVariants selectionSetVariants) { Path rootSelectionPath = Path.Root.Append(context.OperationName); FragmentNode returnTypeFragment = FragmentHelper.CreateFragmentNode( context.OperationType, rootSelectionPath, selectionSetVariants.ReturnType); returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment); OutputTypeModel returnType = FragmentHelper.CreateInterface( context, returnTypeFragment, rootSelectionPath); FragmentHelper.CreateClass( context, returnTypeFragment, selectionSetVariants.ReturnType, returnType); return(returnType); }
private static void CollectOutputTypes(IDocumentAnalyzerContext context, DocumentNode document) { var backlog = new Queue <FieldSelection>(); foreach (OperationDefinitionNode operation in document.Definitions.OfType <OperationDefinitionNode>()) { var root = Path.New(operation.Name !.Value); ObjectType operationType = context.Schema.GetOperationType(operation.Operation); VisitOperationSelectionSet(context, operation, operationType, root, backlog); while (backlog.Any()) { FieldSelection current = backlog.Dequeue(); Path path = current.Path.Append(current.ResponseName); if (!current.Field.Type.NamedType().IsLeafType()) { VisitFieldSelectionSet( context, operation, current.Selection, current.Field.Type, path, backlog); } } RegisterOperationModel(context, document, operation); } }
protected ComplexOutputTypeModel CreateClassModel( IDocumentAnalyzerContext context, IFragmentNode returnTypeFragment, ComplexOutputTypeModel returnType, SelectionInfo selection, Path path) { var fieldNames = new HashSet <string>( selection.Fields.Select(t => GetPropertyName(t.ResponseName))); string className = context.GetOrCreateName( returnTypeFragment.Fragment.SelectionSet, GetClassName(returnTypeFragment.Name), fieldNames); var modelClass = new ComplexOutputTypeModel( className, returnTypeFragment.Fragment.TypeCondition.Description, false, returnTypeFragment.Fragment.TypeCondition, returnTypeFragment.Fragment.SelectionSet, new[] { returnType }, CreateFields( (IComplexOutputType)returnTypeFragment.Fragment.TypeCondition, selection.SelectionSet.Selections, n => true, path)); context.Register(modelClass); return(modelClass); }
private static void RegisterInputObjectType( IDocumentAnalyzerContext context, InputObjectType inputObjectType) { RenameDirective?rename; var fields = new List <InputFieldModel>(); foreach (IInputField inputField in inputObjectType.Fields) { rename = inputField.Directives.SingleOrDefault <RenameDirective>(); fields.Add(new InputFieldModel( GetClassName(rename?.Name ?? inputField.Name), inputField.Description, inputField, inputField.Type)); context.RegisterType(inputField.Type.NamedType()); } rename = inputObjectType.Directives.SingleOrDefault <RenameDirective>(); NameString typeName = context.ResolveTypeName( GetClassName(rename?.Name ?? inputObjectType.Name)); context.RegisterModel( typeName, new InputObjectTypeModel( GetClassName(rename?.Name ?? inputObjectType.Name), inputObjectType.Description, inputObjectType, fields)); }
public abstract void Analyze( IDocumentAnalyzerContext context, OperationDefinitionNode operation, FieldNode fieldSelection, PossibleSelections possibleSelections, IType fieldType, T namedType, Path path);
protected ComplexOutputTypeModel CreateInterfaceModel( IDocumentAnalyzerContext context, IFragmentNode returnTypeFragment, Path path) { var levels = new Stack <ISet <string> >(); levels.Push(new HashSet <string>()); return(CreateInterfaceModel(context, returnTypeFragment, path, levels)); }
private static void CollectOutputTypes( IDocumentAnalyzerContext context, IEnumerable <DocumentNode> documents) { foreach (DocumentNode document in documents) { context.SetDocument(document); CollectOutputTypes(context, document); } }
private static void VisitFieldSelectionSet( IDocumentAnalyzerContext context, OperationDefinitionNode operation, FieldNode fieldSelection, IType fieldType, Path path, Queue <FieldSelection> backlog) { var namedType = (INamedOutputType)fieldType.NamedType(); PossibleSelections possibleSelections = context.CollectFields( namedType, fieldSelection.SelectionSet !, path); foreach (SelectionInfo selectionInfo in possibleSelections.Variants) { EnqueueFields(backlog, selectionInfo.Fields, path); } if (namedType is UnionType unionType) { _unionTypeSelectionSetAnalyzer.Analyze( context, operation, fieldSelection, possibleSelections, fieldType, unionType, path); } else if (namedType is InterfaceType interfaceType) { _interfaceTypeSelectionSetAnalyzer.Analyze( context, operation, fieldSelection, possibleSelections, fieldType, interfaceType, path); } else if (namedType is ObjectType objectType) { _objectTypeSelectionSetAnalyzer.Analyze( context, operation, fieldSelection, possibleSelections, fieldType, objectType, path); } }
private ComplexOutputTypeModel CreateInterfaceModel( IDocumentAnalyzerContext context, IFragmentNode fragmentNode, Path path, Stack <ISet <string> > levels) { NameString name = context.GetOrCreateName( fragmentNode.Fragment.SelectionSet, GetInterfaceName(fragmentNode.Name)); if (context.TryGetModel(name, out ComplexOutputTypeModel? typeModel)) { return(typeModel); } ISet <string> implementedFields = levels.Peek(); IReadOnlyList <OutputFieldModel> fieldModels = Array.Empty <OutputFieldModel>(); IReadOnlyList <ComplexOutputTypeModel> implements = CreateChildInterfaceModels( context, fragmentNode, path, levels, implementedFields); if (fragmentNode.Fragment.TypeCondition is IComplexOutputType type) { fieldModels = CreateFields( type, fragmentNode.Fragment.SelectionSet.Selections, name => { if (implementedFields.Add(name)) { return(true); } return(false); }, path); } typeModel = new ComplexOutputTypeModel( name, fragmentNode.Fragment.TypeCondition.Description, true, fragmentNode.Fragment.TypeCondition, fragmentNode.Fragment.SelectionSet, implements, fieldModels); context.Register(typeModel); return(typeModel); }
protected static FieldParserModel CreateFieldParserModel( IDocumentAnalyzerContext context, OperationDefinitionNode operation, FieldNode fieldSelection, Path path, ComplexOutputTypeModel returnType, IType fieldType, ComplexOutputTypeModel modelType) => CreateFieldParserModel( context, operation, fieldSelection, path, returnType, fieldType, new[] { modelType });
private OutputTypeModel AnalyzeWithDefaults( IDocumentAnalyzerContext context, FieldSelection fieldSelection, SelectionSetVariants selectionVariants) { FragmentNode returnTypeFragment = FragmentHelper.CreateFragmentNode( selectionVariants.ReturnType, fieldSelection.Path); OutputTypeModel returnType = FragmentHelper.CreateInterface( context, returnTypeFragment, fieldSelection.Path); context.RegisterSelectionSet( returnType.Type, selectionVariants.ReturnType.SyntaxNode, returnType.SelectionSet); foreach (SelectionSet selectionSet in selectionVariants.Variants) { returnTypeFragment = FragmentHelper.CreateFragmentNode( selectionSet, fieldSelection.Path, appendTypeName: true); returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment); OutputTypeModel @interface = FragmentHelper.CreateInterface( context, returnTypeFragment, fieldSelection.Path, new[] { returnType }); OutputTypeModel @class = FragmentHelper.CreateClass( context, returnTypeFragment, selectionSet, @interface); context.RegisterSelectionSet( selectionSet.Type, selectionSet.SyntaxNode, @class.SelectionSet); } return(returnType); }
private static void CollectEnumTypes( IDocumentAnalyzerContext context) { var analyzer = new EnumTypeUsageAnalyzer(context.Schema); analyzer.Analyze(context.Document); foreach (EnumType enumType in analyzer.EnumTypes) { RenameDirective?rename; var values = new List <EnumValueModel>(); foreach (IEnumValue enumValue in enumType.Values) { rename = enumValue.Directives.SingleOrDefault <RenameDirective>(); EnumValueDirective?value = enumValue.Directives.SingleOrDefault <EnumValueDirective>(); values.Add(new EnumValueModel( rename?.Name ?? GetEnumValue(enumValue.Name), enumValue.Description, enumValue, value?.Value)); } rename = enumType.Directives.SingleOrDefault <RenameDirective>(); SerializationTypeDirective?serializationType = enumType.Directives.SingleOrDefault <SerializationTypeDirective>(); NameString typeName = context.ResolveTypeName( rename?.Name ?? GetClassName(enumType.Name)); context.RegisterModel( typeName, new EnumTypeModel( typeName, enumType.Description, enumType, serializationType?.Name, values)); } }
private static void CollectEnumTypes( IDocumentAnalyzerContext context, IEnumerable <DocumentNode> documents) { var analyzer = new EnumTypeUsageAnalyzer(context.Schema); foreach (DocumentNode document in documents) { analyzer.Analyze(document); } foreach (EnumType enumType in analyzer.EnumTypes) { RenameDirective?rename; var values = new List <EnumValueModel>(); foreach (EnumValue enumValue in enumType.Values) { rename = enumValue.Directives.SingleOrDefault <RenameDirective>(); EnumValueDirective?value = enumValue.Directives.SingleOrDefault <EnumValueDirective>(); values.Add(new EnumValueModel( GetClassName(rename?.Name ?? enumValue.Name), enumValue, enumValue.Description, value?.Value)); } rename = enumType.Directives.SingleOrDefault <RenameDirective>(); SerializationTypeDirective?serializationType = enumType.Directives.SingleOrDefault <SerializationTypeDirective>(); context.Register(new EnumTypeModel( GetClassName(rename?.Name ?? enumType.Name), enumType.Description, enumType, serializationType?.Name, values)); } }
private static void CollectInputObjectTypes( IDocumentAnalyzerContext context) { var analyzer = new InputObjectTypeUsageAnalyzer(context.Schema); analyzer.Analyze(context.Document); foreach (INamedInputType namedInputType in analyzer.InputTypes) { if (namedInputType is InputObjectType inputObjectType) { RegisterInputObjectType(context, inputObjectType); } else if (namedInputType is ILeafType) { context.RegisterType(namedInputType); } } }
protected static FieldParserModel CreateFieldParserModel( IDocumentAnalyzerContext context, OperationDefinitionNode operation, FieldNode fieldSelection, Path path, ComplexOutputTypeModel returnType, IType fieldType, IReadOnlyList <ComplexOutputTypeModel> possibleTypes) { var parserModel = new FieldParserModel( operation, fieldSelection, path, returnType, fieldType, possibleTypes); context.Register(parserModel); return(parserModel); }
public override OutputTypeModel Analyze( IDocumentAnalyzerContext context, FieldSelection fieldSelection, SelectionSetVariants selectionVariants) { var returnTypeFragmentName = FragmentHelper.GetReturnTypeName(fieldSelection); if (returnTypeFragmentName is null) { return(AnalyzeWithDefaults( context, fieldSelection, selectionVariants)); } return(AnalyzeWithHoistedFragment( context, fieldSelection, selectionVariants, returnTypeFragmentName)); }
private static IReadOnlyList <ArgumentModel> CreateOperationArguments( IDocumentAnalyzerContext context, OperationDefinitionNode operationDefinition) { var arguments = new List <ArgumentModel>(); foreach (VariableDefinitionNode variableDefinition in operationDefinition.VariableDefinitions) { INamedInputType namedInputType = context.Schema.GetType <INamedInputType>( variableDefinition.Type.NamedType().Name.Value); arguments.Add(new ArgumentModel( variableDefinition.Variable.Name.Value, (IInputType)variableDefinition.Type.ToType(namedInputType), variableDefinition, variableDefinition.DefaultValue)); } return(arguments); }
private static DocumentModel CreateDocumentModel( IDocumentAnalyzerContext context, string name, DocumentNode original, IDocumentHashProvider hashProvider) { DocumentNode optimized = TypeNameQueryRewriter.Rewrite(original); string serialized = QuerySyntaxSerializer.Serialize(optimized, false); byte[] buffer = Encoding.UTF8.GetBytes(serialized); string hash = hashProvider.ComputeHash(buffer); return(new DocumentModel( name, context.Operations.Where(t => t.Document == original).ToArray(), original, optimized, buffer, hashProvider.Name, hash)); }
private static void CollectInputObjectTypes( IDocumentAnalyzerContext context) { var analyzer = new InputObjectTypeUsageAnalyzer(context.Schema); analyzer.Analyze(context.Document); foreach (InputObjectType inputObjectType in analyzer.InputObjectTypes) { RenameDirective?rename; var fields = new List <InputFieldModel>(); foreach (IInputField inputField in inputObjectType.Fields) { rename = inputField.Directives.SingleOrDefault <RenameDirective>(); fields.Add(new InputFieldModel( GetClassName(rename?.Name ?? inputField.Name), inputField.Description, inputField, inputField.Type)); } rename = inputObjectType.Directives.SingleOrDefault <RenameDirective>(); NameString typeName = context.ResolveTypeName( GetClassName(rename?.Name ?? inputObjectType.Name)); context.RegisterModel( typeName, new InputObjectTypeModel( GetClassName(rename?.Name ?? inputObjectType.Name), inputObjectType.Description, inputObjectType, fields)); } }
private static void CollectInputObjectTypes( IDocumentAnalyzerContext context, IEnumerable <DocumentNode> documents) { var analyzer = new InputObjectTypeUsageAnalyzer(context.Schema); foreach (DocumentNode document in documents) { analyzer.Analyze(document); } foreach (InputObjectType inputObjectType in analyzer.InputObjectTypes) { RenameDirective?rename; var fields = new List <InputFieldModel>(); foreach (IInputField inputField in inputObjectType.Fields) { rename = inputField.Directives.SingleOrDefault <RenameDirective>(); fields.Add(new InputFieldModel( GetClassName(rename?.Name ?? inputField.Name), inputField.Description, inputField, inputField.Type)); } rename = inputObjectType.Directives.SingleOrDefault <RenameDirective>(); context.Register(new ComplexInputTypeModel( GetClassName(rename?.Name ?? inputObjectType.Name), inputObjectType.Description, inputObjectType, fields)); } }
private static void VisitOperationSelectionSet( IDocumentAnalyzerContext context, OperationDefinitionNode operation, ObjectType operationType, Path path, Queue <FieldSelection> backlog) { PossibleSelections possibleSelections = context.CollectFields( operationType, operation.SelectionSet, path); EnqueueFields(backlog, possibleSelections.ReturnType.Fields, path); _objectTypeSelectionSetAnalyzer.Analyze( context, operation, new FieldNode( null, new NameNode(operation.Name !.Value), null, new[] { new DirectiveNode( GeneratorDirectives.Type, new ArgumentNode("name", operation.Name.Value)), new DirectiveNode(GeneratorDirectives.Operation) }, Array.Empty <ArgumentNode>(), null), possibleSelections, new NonNullType(operationType), operationType, path); }
public abstract OutputTypeModel Analyze( IDocumentAnalyzerContext context, FieldSelection fieldSelection, SelectionSetVariants selectionSetVariants);
private OutputTypeModel AnalyzeWithHoistedFragment( IDocumentAnalyzerContext context, FieldSelection fieldSelection, SelectionSetVariants selectionVariants, string fragmentName) { FragmentNode?returnTypeFragment = FragmentHelper.CreateFragmentNode( selectionVariants.Variants[0], fieldSelection.Path, appendTypeName: true); returnTypeFragment = FragmentHelper.GetFragment(returnTypeFragment, fragmentName); if (returnTypeFragment is null) { // TODO : throw helper throw new GraphQLException( "The specified return fragment does not exist."); } OutputTypeModel returnType = FragmentHelper.CreateInterface(context, returnTypeFragment, fieldSelection.Path); context.RegisterSelectionSet( returnType.Type, selectionVariants.ReturnType.SyntaxNode, returnType.SelectionSet); foreach (SelectionSet selectionSet in selectionVariants.Variants) { returnTypeFragment = FragmentHelper.CreateFragmentNode( selectionSet, fieldSelection.Path, appendTypeName: true); returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment); if (FragmentHelper.GetFragment(returnTypeFragment, fragmentName) is null) { // TODO : throw helper throw new GraphQLException( "The specified return fragment must be implement by all type fragments."); } OutputTypeModel @interface = FragmentHelper.CreateInterface( context, returnTypeFragment, fieldSelection.Path, new[] { returnType }); OutputTypeModel @class = FragmentHelper.CreateClass( context, returnTypeFragment, selectionSet, @interface); context.RegisterSelectionSet( selectionSet.Type, selectionSet.SyntaxNode, @class.SelectionSet); } return(returnType); }
private OutputTypeModel AnalyzeWithHoistedFragment( IDocumentAnalyzerContext context, FieldSelection fieldSelection, SelectionSetVariants selectionVariants, string fragmentName) { FragmentNode?returnTypeFragment = FragmentHelper.CreateFragmentNode( selectionVariants.Variants[0], fieldSelection.Path, appendTypeName: true); returnTypeFragment = FragmentHelper.GetFragment(returnTypeFragment, fragmentName); if (returnTypeFragment is null) { throw ThrowHelper.ReturnFragmentDoesNotExist(); } OutputTypeModel returnType = FragmentHelper.CreateInterface(context, returnTypeFragment, fieldSelection.Path); context.RegisterSelectionSet( returnType.Type, selectionVariants.ReturnType.SyntaxNode, returnType.SelectionSet); foreach (SelectionSet selectionSet in selectionVariants.Variants) { returnTypeFragment = FragmentHelper.CreateFragmentNode( selectionSet, fieldSelection.Path, appendTypeName: true); returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment); if (FragmentHelper.GetFragment(returnTypeFragment, fragmentName) is null) { throw ThrowHelper.FragmentMustBeImplementedByAllTypeFragments(); } OutputTypeModel @interface = FragmentHelper.CreateInterface( context, returnTypeFragment, fieldSelection.Path, new[] { returnType }); OutputTypeModel @class = FragmentHelper.CreateClass( context, returnTypeFragment, selectionSet, @interface); context.RegisterSelectionSet( selectionSet.Type, selectionSet.SyntaxNode, @class.SelectionSet); } return(returnType); }
protected IReadOnlyList <ComplexOutputTypeModel> CreateClassModels( IDocumentAnalyzerContext context, ComplexOutputTypeModel returnType, FieldNode fieldSelection, IReadOnlyCollection <SelectionInfo> selections, Path path) { var possibleModelTypes = new List <ComplexOutputTypeModel>(); foreach (SelectionInfo selection in selections) { IFragmentNode modelType = ResolveReturnType( selection.Type, fieldSelection, selection); var interfaces = new List <ComplexOutputTypeModel>(); foreach (IFragmentNode fragment in ShedNonMatchingFragments( selection.Type, modelType)) { interfaces.Add(CreateInterfaceModel(context, fragment, path)); } interfaces.Insert(0, returnType); NameString typeName = HoistName(selection.Type, modelType); if (typeName.IsEmpty) { typeName = selection.Type.Name; } bool update = false; var fieldNames = new HashSet <string>( selection.Fields.Select(t => GetPropertyName(t.ResponseName))); string className = context.GetOrCreateName( modelType.Fragment.SelectionSet, GetClassName(typeName), fieldNames); if (context.TryGetModel(className, out ComplexOutputTypeModel? model)) { var interfaceNames = new HashSet <string>(interfaces.Select(t => t.Name)); foreach (ComplexOutputTypeModel type in model.Types.Reverse()) { if (interfaceNames.Add(type.Name)) { interfaces.Insert(0, type); } } update = true; } model = new ComplexOutputTypeModel( className, modelType.Fragment.TypeCondition.Description, false, modelType.Fragment.TypeCondition, selection.SelectionSet, interfaces, CreateFields( (IComplexOutputType)modelType.Fragment.TypeCondition, selection.SelectionSet.Selections, n => true, path)); context.Register(model, update); possibleModelTypes.Add(model); } return(possibleModelTypes); }