Issue 1:
Hi,

I think I may have found a bug in ValidatorTypeGuesser , either that or this is quite an unexpected behavior.

Validator guesser for required (guessRequired) does not seem to work properly when there is no constraint defined for a given property at all.

The documentation says: "The required option can be guessed based on the validation rules (i.e. is the field NotBlank or NotNull)"

Which seems to be confirmed by the source code comments in ValidatorTypeGuesser.php:

// If we don't find any constraint telling otherwise, we can assume
// that a field is not required (with LOW_CONFIDENCE)

however this is not happening if no constraints are defined at all, it does work properly when a non-related constraint is defined (any constraint)

to reproduce:

The form:

class TestFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add("name")
->add("comments");
}
public function getName()
{
return "test_form";
}
}

The entity:

class TestEntity
{
private $name;
private $comments;

// ... getters and setters ...
}

The validator:

<class name="FormExperiment\TestBundle\Entity\TestEntity">
<property name="name">
<constraint name="NotBlank" />
</property>
</class>

and in the controller simply:

$form = $this->createForm(new TestFormType(), new TestEntity());

and then just pass $form->createView() to the template

Expected behavior:

name has required="required", and comments doesn't have it.

What actually happens:

Both name and comments have required="required"

If you add any constraint to 'comments', like:

<property name="comments">
<constraint name="Length">
<option name="max">5</option>
</constraint>
</property>

then it will guess the required option properly (in this case required is false since the constraint is not NotNull or NotBlank)

even more bizarre that if I override the default in the form type with:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'required' => false
));
}

then both will miss required="required" regardless of the guessing altogether, seems like the default option is stronger than anything else.

I managed to trace the problem and make the guesser work though:

The main problem is that since constraints are not present for comments at all the whole guessing is skipped here (ValidatorTypeGuesser.php):

protected function guess($class, $property, \Closure $closure, $defaultValue = null)
{
$guesses = array();
$classMetadata = $this->metadataFactory->getMetadataFor($class);

if ($classMetadata->hasMemberMetadatas($property)) {
$memberMetadatas = $classMetadata->getMemberMetadatas($property);

foreach ($memberMetadatas as $memberMetadata) {
$constraints = $memberMetadata->getConstraints();

foreach ($constraints as $constraint) {
if ($guess = $closure($constraint)) {
$guesses[] = $guess;
}
}
}

if (null !== $defaultValue) {
$guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE);
}
}

return Guess::getBestGuess($guesses);
}

the condition if ($classMetadata->hasMemberMetadatas($property)) skips the entire guess because of this. this condition does not seem to be neccessary since in the next line:

$memberMetadatas = $classMetadata->getMemberMetadatas($property);

getMemberMetadatas has a guard for missing metadata anyway and returns an empty array in that case which then skips through the foreach and does a false valueguess for required as it should.

If I remove this condition everything works fine. the guess actually makes it through and works properly. I could not find a good reason why this condition is here but someone more familiar with the code might know better.

Regards

Issue 2:
A mistake that I frequently see is that people forget to call createView() when passing a form to the view. What do you think about converting FormInterface instances to FormView objects automatically by calling createView(), for example, in a listener?