@Override
 public Optional<Invokable> getMethod(
     String method, boolean staticContext, Map<String, TypeUsage> typeParams) {
   ensureIsInitialized(symbolResolver());
   Set<InternalMethodDefinition> methods = Collections.emptySet();
   if (methodsByName.containsKey(method)) {
     methods =
         methodsByName
             .get(method)
             .stream()
             .filter((m) -> m.getJvmMethodDefinition().isStatic() == staticContext)
             .collect(Collectors.toSet());
   }
   if (methods.isEmpty()) {
     return Optional.empty();
   } else {
     return Optional.of(new MethodSetAsInvokableType(methods, typeParams));
   }
 }
  private void initializeImplicitConstructor(SymbolResolver resolver) {
    List<? extends FormalParameter> inheritedParams = Collections.emptyList();
    if (getBaseType().isPresent()) {
      List<InternalConstructorDefinition> constructors =
          getBaseType().get().asReferenceTypeUsage().getTypeDefinition().getConstructors();
      if (constructors.size() != 1) {
        throw new UnsupportedOperationException();
      }
      inheritedParams = constructors.get(0).getFormalParameters();
    }

    List<FormalParameterNode> newParams =
        this.assignableProperties(resolver)
            .stream()
            .map(
                (p) ->
                    new FormalParameterNode(
                        p.getTypeUsage().copy(), p.getName(), p.getDefaultValue()))
            .collect(Collectors.toList());
    List<FormalParameter> allParams = new LinkedList<>();
    allParams.addAll(inheritedParams);
    allParams.addAll(newParams);
    allParams.sort(
        new Comparator<FormalParameter>() {
          @Override
          public int compare(FormalParameter o1, FormalParameter o2) {
            return Boolean.compare(o1.hasDefaultValue(), o2.hasDefaultValue());
          }
        });
    for (FormalParameter p : allParams) {
      // needed to solve symbols
      if (p.isNode()) {
        p.asNode().setParent(this);
      }
    }
    addConstructorWithParams(allParams, resolver);
  }
 private void initializeMethodsByName(SymbolResolver resolver) {
   methodsByName = new HashMap<>();
   // TODO methods inherited by Object
   // TODO if we implement inheritance also other methods inherited from classes or interfaces
   for (Property property : getDirectProperties(resolver)) {
     {
       String descriptor = "()" + property.getTypeUsage().jvmType().getDescriptor();
       JvmMethodDefinition jvmMethodDefinition =
           new JvmMethodDefinition(
               getInternalName(), property.getterName(resolver), descriptor, false, false);
       InternalMethodDefinition getter =
           new InternalMethodDefinition(
               property.getterName(resolver),
               Collections.emptyList(),
               property.getTypeUsage(),
               jvmMethodDefinition);
       registerMethod(getter);
     }
     {
       String descriptor = "(" + property.getTypeUsage().jvmType().getDescriptor() + ")V";
       JvmMethodDefinition jvmMethodDefinition =
           new JvmMethodDefinition(
               getInternalName(), property.setterName(), descriptor, false, false);
       FormalParameterNode param =
           new FormalParameterNode(property.getTypeUsage().copy(), property.getName());
       param.setParent(this);
       InternalMethodDefinition setter =
           new InternalMethodDefinition(
               property.setterName(),
               ImmutableList.of(param),
               new VoidTypeUsageNode(),
               jvmMethodDefinition);
       registerMethod(setter);
     }
   }
 }
 @Override
 public <T extends TypeUsage> Map<String, TypeUsage> associatedTypeParametersToName(
     List<T> typeParams) {
   return Collections.emptyMap();
 }
 /** Does it override the hashCode method defined in Object? */
 public boolean defineMethodHashCode(SymbolResolver resolver) {
   return isDefiningMethod("hashCode", Collections.emptyList(), resolver);
 }
 /** Does it override the toString method defined in Object? */
 public boolean defineMethodToString(SymbolResolver resolver) {
   return isDefiningMethod("toString", Collections.emptyList(), resolver);
 }