public function getProperties($filter = null)
    {
        if (!isset($this->properties)) {
            $directProperties = ReflectionProperty::collectFromClassNode($this->classLikeNode, $this->getName());
            $parentProperties = $this->recursiveCollect(function (array &$result, \ReflectionClass $instance, $isParent) {
                $reflectionProperties = [];
                foreach ($instance->getProperties() as $reflectionProperty) {
                    if (!$isParent || !$reflectionProperty->isPrivate()) {
                        $reflectionProperties[$reflectionProperty->name] = $reflectionProperty;
                    }
                }
                $result += $reflectionProperties;
            });
            $properties = $directProperties + $parentProperties;

            $this->properties = $properties;
        }

        // Without filter we can just return the full list
        if (!isset($filter)) {
            return array_values($this->properties);
        }

        $properties = [];
        foreach ($this->properties as $property) {
            if (!($filter & $property->getModifiers())) {
                continue;
            }
            $properties[] = $property;
        }

        return $properties;
    }