func (itc *irgTypeConstructor) DecorateMembers(decorator typegraph.GetMemberDecorator, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) { for _, declaration := range itc.irg.Declarations() { if declaration.HasAnnotation(CONSTRUCTOR_ANNOTATION) { // For each constructor defined, create the intersection of their parameters. var parameters = make([]typegraph.TypeReference, 0) for constructorIndex, constructor := range declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION) { for index, parameter := range constructor.Parameters() { parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph) if err != nil { reporter.ReportError(parameter.GraphNode, "%v", err) continue } var resolvedParameterType = parameterType if parameter.IsOptional() { resolvedParameterType = resolvedParameterType.AsNullable() } if index >= len(parameters) { // If this is not the first constructor, then this parameter is implicitly optional // and therefore nullable. if constructorIndex > 0 { resolvedParameterType = resolvedParameterType.AsNullable() } parameters = append(parameters, resolvedParameterType) } else { parameters[index] = parameters[index].Intersect(resolvedParameterType) } } } // Define the construction function for the type. typeDecl, _ := graph.GetTypeForSourceNode(declaration.GraphNode) var constructorFunction = graph.FunctionTypeReference(typeDecl.GetTypeReference()) for _, parameterType := range parameters { constructorFunction = constructorFunction.WithParameter(parameterType) } decorator(declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION)[0].GraphNode). Exported(true). Static(true). ReadOnly(true). MemberKind(typegraph.NativeConstructorMemberSignature). MemberType(constructorFunction). Decorate() } for _, nativeOp := range declaration.GetAnnotations(NATIVE_OPERATOR_ANNOTATION) { opName, hasOpName := nativeOp.Value() if !hasOpName { continue } opDefinition, found := graph.GetOperatorDefinition(opName) if !found { continue } // Define the operator's member type based on the definition. typeDecl, _ := graph.GetTypeForSourceNode(declaration.GraphNode) var expectedReturnType = opDefinition.ExpectedReturnType(typeDecl.GetTypeReference()) if expectedReturnType.HasReferredType(graph.BoolType()) { expectedReturnType, _ = itc.ResolveType("Boolean", graph) } var operatorType = graph.FunctionTypeReference(expectedReturnType) for _, parameter := range opDefinition.Parameters { operatorType = operatorType.WithParameter(parameter.ExpectedType(typeDecl.GetTypeReference())) } // Add the operator to the type. decorator(nativeOp.GraphNode). Native(true). Exported(true). SkipOperatorChecking(true). MemberType(operatorType). MemberKind(typegraph.NativeOperatorMemberSignature). Decorate() } // Add the declared members. for _, member := range declaration.Members() { declaredType, err := itc.ResolveType(member.DeclaredType(), graph) if err != nil { reporter.ReportError(member.GraphNode, "%v", err) continue } var memberType = declaredType var memberKind = typegraph.CustomMemberSignature var isReadonly = member.IsReadonly() switch member.Kind() { case webidl.FunctionMember: isReadonly = true memberKind = typegraph.NativeFunctionMemberSignature memberType = graph.FunctionTypeReference(memberType) // Add the parameter types. var markOptional = false for _, parameter := range member.Parameters() { if parameter.IsOptional() { markOptional = true } parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph) if err != nil { reporter.ReportError(member.GraphNode, "%v", err) continue } // All optional parameters get marked as nullable, which means we can skip // passing them on function calls. if markOptional { memberType = memberType.WithParameter(parameterType.AsNullable()) } else { memberType = memberType.WithParameter(parameterType) } } case webidl.AttributeMember: memberKind = typegraph.NativePropertyMemberSignature if len(member.Parameters()) > 0 { reporter.ReportError(member.GraphNode, "Attributes cannot have parameters") } default: panic("Unknown WebIDL member kind") } decorator := decorator(member.GraphNode) if _, hasName := member.Name(); !hasName { decorator.Native(true) } decorator.Exported(true). Static(member.IsStatic()). ReadOnly(isReadonly). MemberKind(memberKind). MemberType(memberType). Decorate() } } }