@Override
 public Number measure(final MetricData data, final Def_Function function) {
   final Counter c = new Counter(0);
   final Module myModule = function.getMyScope().getModuleScope();
   function.accept(new ExternalFeatureEnvyDetector(myModule, c));
   return c.val();
 }
  /**
   * Does the semantic checking of the type mapping.
   *
   * @param timestamp the timestamp of the actual semantic check cycle.
   */
  public void check(final CompilationTimeStamp timestamp) {
    if (lastTimeChecked != null && !lastTimeChecked.isLess(timestamp)) {
      return;
    }

    if (source_type != null) {
      source_type.check(timestamp);
    }

    int nofTargets = mappingTargets.getNofTargets();
    boolean hasSliding = false;
    boolean hasNonSliding = false;
    for (int i = 0, size = nofTargets; i < size; i++) {
      TypeMappingTarget target = mappingTargets.getTargetByIndex(i);
      target.check(timestamp, source_type);
      if (nofTargets > 1) {
        switch (target.getTypeMappingType()) {
          case DISCARD:
            if (hasSliding) {
              target
                  .getLocation()
                  .reportSemanticError(
                      "Mapping `discard' cannot be used if functions with `prototype(sliding)' are referred from the same source type");
            } else if (i < nofTargets - 1) {
              target
                  .getLocation()
                  .reportSemanticError(
                      "Mapping `discard' must be the last target of the source type");
            }
            break;
          case FUNCTION:
            {
              Def_Function function = ((FunctionTypeMappingTarget) target).getFunction();
              Def_Extfunction externalFunction =
                  ((FunctionTypeMappingTarget) target).getExternalFunction();
              EncodingPrototype_type prototype = EncodingPrototype_type.NONE;
              if (function != null) {
                prototype = function.getPrototype();
              } else if (externalFunction != null) {
                prototype = externalFunction.getPrototype();
              } else {
                continue;
              }

              switch (prototype) {
                case NONE:
                  break;
                case BACKTRACK:
                  hasNonSliding = true;
                  break;
                case SLIDING:
                  hasSliding = true;
                  break;
                default:
                  if (function != null) {
                    final String message =
                        MessageFormat.format(
                            "The referenced {0} must have the attribute `prototype(backtrack)'' or `prototype(sliding)'' when more than one targets are present",
                            function.getDescription());
                    target.getLocation().reportSemanticError(message);
                  } else if (externalFunction != null) {
                    final String message =
                        MessageFormat.format(
                            "The referenced {0} must have the attribute `prototype(backtrack)'' or `prototype(sliding)'' when more than one targets are present",
                            externalFunction.getDescription());
                    target.getLocation().reportSemanticError(message);
                  }
                  break;
              }

              break;
            }
          case DECODE:
            break;
          default:
            target
                .getLocation()
                .reportSemanticError(
                    MessageFormat.format(
                        "The type of the mapping must be `function', `decode',"
                            + " or `discard' instead of {0} when more than one targets are present",
                        target.getMappingName()));
            break;
        }
      }
    }

    if (hasSliding && hasNonSliding) {
      location.reportSemanticError(
          "If one of the mappings refers to a function with attribute `prototype(sliding)'"
              + "then mappings of this source type cannot refer to functions with attribute `prototype(backtrack)'");
    }

    lastTimeChecked = timestamp;
  }