示例#1
0
func isTypeRecursive(typ ast.Type) (bool, []ast.Type) {
	typ = typ.ActualType()

	var check func(current ast.Type, path *[]ast.Type, traversed map[ast.Type]bool) bool
	check = func(current ast.Type, path *[]ast.Type, traversed map[ast.Type]bool) bool {
		switch current.(type) {
		case *ast.NamedType:
			if traversed[current] {
				return true
			}
		}

		switch typ := current.(type) {
		case ast.StructType:
			for _, mem := range typ.Members {
				if check(mem.Type.BaseType, path, traversed) {
					*path = append(*path, mem.Type.BaseType)
					return true
				}
			}

		case ast.TupleType:
			for _, mem := range typ.Members {
				if check(mem.BaseType, path, traversed) {
					*path = append(*path, mem.BaseType)
					return true
				}
			}

		case ast.EnumType:
			for _, mem := range typ.Members {
				if check(mem.Type, path, traversed) {
					*path = append(*path, mem.Type)
					return true
				}
			}

		case *ast.NamedType:
			traversed[current] = true
			if check(typ.Type, path, traversed) {
				*path = append(*path, typ.Type)
				return true
			}
			traversed[current] = false

		case ast.ArrayType:
			if typ.IsFixedLength && check(typ.MemberType.BaseType, path, traversed) {
				*path = append(*path, typ.MemberType.BaseType)
				return true
			}
		}
		return false
	}

	var path []ast.Type
	return check(typ, &path, make(map[ast.Type]bool)), path
}
示例#2
0
func typeContainsReferenceType(typ ast.Type, visited map[*ast.TypeReference]struct{ visited, value bool }) bool {
	switch typ := typ.ActualType().(type) {
	case ast.ReferenceType:
		return true

	case ast.PointerType:
		return typeReferenceContainsReferenceType(typ.Addressee, visited)

	case ast.ArrayType:
		return typeReferenceContainsReferenceType(typ.MemberType, visited)

	case ast.StructType:
		for _, field := range typ.Members {
			if typeReferenceContainsReferenceType(field.Type, visited) {
				return true
			}
		}
		return false

	case ast.EnumType:
		for _, member := range typ.Members {
			if typeContainsReferenceType(member.Type, visited) {
				return true
			}
		}
		return false

	case ast.TupleType:
		for _, field := range typ.Members {
			if typeReferenceContainsReferenceType(field, visited) {
				return true
			}
		}
		return false

	case *ast.SubstitutionType, ast.PrimitiveType, ast.FunctionType:
		return false

	default:
		panic("unimplemented type: " + reflect.TypeOf(typ).String())
	}
}