Example #1
0
// defineMember defines a single type member under a type or module.
func (stc *srgTypeConstructor) defineMember(member srg.SRGMember, parent typegraph.TGTypeOrModule, builder *typegraph.MemberBuilder, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
	// Define the member's name and source node.
	builder.Name(member.Name()).
		SourceNode(member.Node())

	// Add the member's generics.
	for _, generic := range member.Generics() {
		builder.WithGeneric(generic.Name(), generic.Node())
	}

	builder.Define()
}
Example #2
0
// addSRGParameterTypes iterates over the parameters defined on the given srgMember, adding their types as parameters
// to the specified base type reference.
func (stc *srgTypeConstructor) addSRGParameterTypes(member srg.SRGMember, baseReference typegraph.TypeReference, tdg *typegraph.TypeGraph, reporter typegraph.IssueReporter) (typegraph.TypeReference, bool) {
	var currentReference = baseReference
	var success = true

	for _, parameter := range member.Parameters() {
		parameterTypeRef, result := stc.resolvePossibleType(member.Node(), parameter.DeclaredType, tdg, reporter)
		if !result {
			success = false
		}

		currentReference = currentReference.WithParameter(parameterTypeRef)
	}

	return currentReference, success
}
Example #3
0
// decorateMember decorates a single type member.
func (stc *srgTypeConstructor) decorateMember(member srg.SRGMember, parent typegraph.TGTypeOrModule, decorator *typegraph.MemberDecorator, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) {
	// Add the generic's constraints.
	for _, generic := range member.Generics() {
		// Note: If the constraint is not valid, the resolve method will report the error and return Any, which is the correct type.
		constraintType, _ := stc.resolvePossibleType(generic.Node(), generic.GetConstraint, graph, reporter)
		decorator.DefineGenericConstraint(generic.Node(), constraintType)
	}

	// Build all member-specific information.
	var memberType typegraph.TypeReference = graph.AnyTypeReference()
	var memberKind typegraph.MemberSignatureKind = typegraph.CustomMemberSignature

	var isReadOnly bool = true
	var isStatic bool = false
	var isPromising bool = true
	var isImplicitlyCalled bool = false
	var hasDefaultValue bool = false
	var isField = false

	switch member.MemberKind() {
	case srg.VarMember:
		// Variables have their declared type.
		memberType, _ = stc.resolvePossibleType(member.Node(), member.DeclaredType, graph, reporter)
		memberKind = typegraph.FieldMemberSignature

		isReadOnly = false
		isPromising = false
		isField = true
		_, hasDefaultValue = member.Node().TryGetNode(parser.NodePredicateTypeFieldDefaultValue)

	case srg.PropertyMember:
		// Properties have their declared type.
		memberType, _ = stc.resolvePossibleType(member.Node(), member.DeclaredType, graph, reporter)
		memberKind = typegraph.PropertyMemberSignature

		isReadOnly = member.IsReadOnly()
		isImplicitlyCalled = true

		// Decorate the property *getter* with its return type.
		getter, found := member.Getter()
		if found {
			decorator.CreateReturnable(getter.GraphNode, memberType)
		}

	case srg.ConstructorMember:
		memberKind = typegraph.ConstructorMemberSignature

		// Constructors are static.
		isStatic = true

		// Constructors have a type of a function that returns an instance of the parent type.
		returnType := graph.NewInstanceTypeReference(parent.(typegraph.TGTypeDecl))
		functionType := graph.NewTypeReference(graph.FunctionType(), returnType)
		memberType, _ = stc.addSRGParameterTypes(member, functionType, graph, reporter)

		// Decorate the constructor with its return type.
		decorator.CreateReturnable(member.Node(), returnType)

		// Constructors have custom signature types that return 'any' to allow them to match
		// interfaces.
		var signatureType = graph.FunctionTypeReference(graph.AnyTypeReference())
		signatureType, _ = stc.addSRGParameterTypes(member, signatureType, graph, reporter)
		decorator.SignatureType(signatureType)

	case srg.OperatorMember:
		memberKind = typegraph.OperatorMemberSignature

		// Operators are read-only.
		isReadOnly = true

		// Operators have type function<DeclaredType>(parameters).
		returnType, _ := stc.resolvePossibleType(member.Node(), member.DeclaredType, graph, reporter)
		functionType := graph.NewTypeReference(graph.FunctionType(), returnType)
		memberType, _ = stc.addSRGParameterTypes(member, functionType, graph, reporter)

		// Make sure instance members under interfaces do not have bodies (and static members do).
		if parent.IsType() {
			parentType := parent.AsType()
			if parentType.TypeKind() == typegraph.ImplicitInterfaceType {
				opDef, found := graph.GetOperatorDefinition(member.Name())

				// Note: If not found, the type graph will emit an error.
				if found {
					if member.HasImplementation() != opDef.IsStatic {
						if opDef.IsStatic {
							reporter.ReportError(member.GraphNode, "Static operator %v under %v %v must have an implementation", member.Name(), parentType.Title(), parentType.Name())
						} else {
							reporter.ReportError(member.GraphNode, "Instance operator %v under %v %v cannot have an implementation", member.Name(), parentType.Title(), parentType.Name())
						}
					}
				}
			}
		}

		// Note: Operators get decorated with a returnable by the construction system automatically.

	case srg.FunctionMember:
		memberKind = typegraph.FunctionMemberSignature

		// Functions are read-only.
		isReadOnly = true

		// Functions have type function<ReturnType>(parameters).
		returnType, _ := stc.resolvePossibleType(member.Node(), member.ReturnType, graph, reporter)

		// Decorate the function with its return type.
		decorator.CreateReturnable(member.Node(), returnType)

		// If the function is an async function, make it non-promising and return a Awaitable instead.
		if member.IsAsyncFunction() {
			isPromising = false
			returnType = graph.AwaitableTypeReference(returnType)
		}

		functionType := graph.NewTypeReference(graph.FunctionType(), returnType)
		memberType, _ = stc.addSRGParameterTypes(member, functionType, graph, reporter)
	}

	// Decorate the member with whether it is exported.
	decorator.Exported(member.IsExported())

	// Decorate the member with whether it is an async function.
	decorator.InvokesAsync(member.IsAsyncFunction())

	// If the member is under a module, then it is static.
	decorator.Static(isStatic || !parent.IsType())

	// Decorate the member with whether it is promising.
	decorator.Promising(isPromising)

	// Decorate the member with whether it has a default value.
	decorator.HasDefaultValue(hasDefaultValue)

	// Decorate the member with whether it is a field.
	decorator.Field(isField)

	// Decorate the member with whether it is implicitly called.
	decorator.ImplicitlyCalled(isImplicitlyCalled)

	// Decorate the member with whether it is read-only.
	decorator.ReadOnly(isReadOnly)

	// Decorate the member with its type.
	decorator.MemberType(memberType)

	// Decorate the member with its kind.
	decorator.MemberKind(memberKind)

	// Decorate the member with its tags, if any.
	for name, value := range member.Tags() {
		decorator.WithTag(name, value)
	}

	// Finalize the member.
	decorator.Decorate()
}