예제 #1
0
// ResolveType attempts to resolve the given type string.
func (itc *irgTypeConstructor) ResolveType(typeString string, graph *typegraph.TypeGraph) (typegraph.TypeReference, error) {
	if typeString == "any" {
		return graph.AnyTypeReference(), nil
	}

	if typeString == "void" {
		return graph.VoidTypeReference(), nil
	}

	var nullable = false
	if strings.HasSuffix(typeString, "?") {
		nullable = true
		typeString = typeString[0 : len(typeString)-1]
	}

	// Perform native type mapping.
	if found, ok := NATIVE_TYPES[typeString]; ok {
		typeString = found
	}

	declaration, hasDeclaration := itc.irg.FindDeclaration(typeString)
	if !hasDeclaration {
		return graph.AnyTypeReference(), fmt.Errorf("Could not find WebIDL type %v", typeString)
	}

	typeDecl, hasType := graph.GetTypeForSourceNode(declaration.GraphNode)
	if !hasType {
		panic("Type not found for WebIDL type declaration")
	}

	typeRef := typeDecl.GetTypeReference()
	if nullable {
		return typeRef.AsNullable(), nil
	}

	return typeRef, nil
}
예제 #2
0
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()
		}
	}
}
예제 #3
0
func (trr *TypeReferenceResolver) resolveTypeRef(typeref srg.SRGTypeRef, tdg *typegraph.TypeGraph) (typegraph.TypeReference, error) {
	switch typeref.RefKind() {
	case srg.TypeRefVoid:
		return tdg.VoidTypeReference(), nil

	case srg.TypeRefAny:
		return tdg.AnyTypeReference(), nil

	case srg.TypeRefStruct:
		return tdg.StructTypeReference(), nil

	case srg.TypeRefMapping:
		innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg)
		if err != nil {
			return tdg.AnyTypeReference(), err
		}

		return tdg.NewTypeReference(tdg.MappingType(), innerType), nil

	case srg.TypeRefSlice:
		innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg)
		if err != nil {
			return tdg.AnyTypeReference(), err
		}

		return tdg.NewTypeReference(tdg.SliceType(), innerType), nil

	case srg.TypeRefStream:
		innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg)
		if err != nil {
			return tdg.AnyTypeReference(), err
		}

		return tdg.NewTypeReference(tdg.StreamType(), innerType), nil

	case srg.TypeRefNullable:
		innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg)
		if err != nil {
			return tdg.AnyTypeReference(), err
		}

		return innerType.AsNullable(), nil

	case srg.TypeRefPath:
		// Resolve the package type for the type ref.
		resolvedTypeInfo, found := typeref.ResolveType()
		if !found {
			sourceError := compilercommon.SourceErrorf(typeref.Location(),
				"Type '%s' could not be found",
				typeref.ResolutionPath())

			return tdg.AnyTypeReference(), sourceError
		}

		// If the type information refers to an SRG type or generic, find the node directly
		// in the type graph.
		var constructedRef = tdg.AnyTypeReference()
		if !resolvedTypeInfo.IsExternalPackage {
			// Get the type in the type graph.
			resolvedType, hasResolvedType := tdg.GetTypeForSourceNode(resolvedTypeInfo.ResolvedType.Node())
			if !hasResolvedType {
				panic(fmt.Sprintf("Could not find typegraph type for SRG type %v", resolvedTypeInfo.ResolvedType.Name()))
			}

			constructedRef = tdg.NewTypeReference(resolvedType)
		} else {
			// Otherwise, we search for the type in the type graph based on the package from which it
			// was imported.
			resolvedType, hasResolvedType := tdg.ResolveTypeUnderPackage(resolvedTypeInfo.ExternalPackageTypePath, resolvedTypeInfo.ExternalPackage)
			if !hasResolvedType {
				sourceError := compilercommon.SourceErrorf(typeref.Location(),
					"Type '%s' could not be found",
					typeref.ResolutionPath())

				return tdg.AnyTypeReference(), sourceError
			}

			constructedRef = tdg.NewTypeReference(resolvedType)
		}

		// Add the generics.
		if typeref.HasGenerics() {
			for _, srgGeneric := range typeref.Generics() {
				genericTypeRef, err := trr.ResolveTypeRef(srgGeneric, tdg)
				if err != nil {
					return tdg.AnyTypeReference(), err
				}

				constructedRef = constructedRef.WithGeneric(genericTypeRef)
			}
		}

		// Add the parameters.
		if typeref.HasParameters() {
			for _, srgParameter := range typeref.Parameters() {
				parameterTypeRef, err := trr.ResolveTypeRef(srgParameter, tdg)
				if err != nil {
					return tdg.AnyTypeReference(), err
				}
				constructedRef = constructedRef.WithParameter(parameterTypeRef)
			}
		}

		return constructedRef, nil

	default:
		panic(fmt.Sprintf("Unknown kind of SRG type ref: %v", typeref.RefKind()))
		return tdg.AnyTypeReference(), nil
	}
}