protected String doDerivePropertyTypeFromTestValue(String testValue) { // test point
   if (testValue == null) {
     String msg = "The argument 'testValue' should be not null.";
     throw new IllegalArgumentException(msg);
   }
   final DfLanguageGrammar grammar = getLanguageGrammar();
   final String plainTypeName;
   if (Srl.startsWithIgnoreCase(testValue, "date '", "date'")) {
     plainTypeName = "Date";
   } else if (Srl.startsWithIgnoreCase(testValue, "timestamp '", "timestamp'")) {
     plainTypeName = "Timestamp";
   } else if (Srl.startsWithIgnoreCase(testValue, "time '", "time'")) {
     plainTypeName = "Time";
   } else {
     if (Srl.isQuotedSingle(testValue)) {
       final String unquoted = Srl.unquoteSingle(testValue);
       Timestamp timestamp = null;
       Time time = null;
       try {
         timestamp = DfTypeUtil.toTimestamp(unquoted);
       } catch (ParseTimestampException ignored) {
         try {
           time = DfTypeUtil.toTime(unquoted);
         } catch (ParseTimeException andIgnored) {
         }
       }
       if (timestamp != null) {
         final String timeParts = DfTypeUtil.toString(timestamp, "HH:mm:ss.SSS");
         if (timeParts.equals("00:00:00.000")) {
           plainTypeName = "Date";
         } else {
           plainTypeName = "Timestamp";
         }
       } else if (time != null) {
         plainTypeName = "Time";
       } else {
         plainTypeName = "String";
       }
     } else if (Srl.isQuotedAnything(testValue, "(", ")")) {
       final String unquoted = Srl.unquoteAnything(testValue, "(", ")");
       final List<String> elementList = Srl.splitListTrimmed(unquoted, ",");
       if (elementList.size() > 0) {
         final String firstElement = elementList.get(0);
         // InScope for Date is unsupported at this analyzing
         if (Srl.isQuotedSingle(firstElement)) {
           plainTypeName = "List" + grammar.buildGenericOneClassHint("String");
         } else {
           final String elementType = doDeriveNonQuotedLiteralTypeFromTestValue(firstElement);
           plainTypeName = "List" + grammar.buildGenericOneClassHint(elementType);
         }
       } else {
         plainTypeName = "List" + grammar.buildGenericOneClassHint("String");
       }
     } else {
       plainTypeName = doDeriveNonQuotedLiteralTypeFromTestValue(testValue);
     }
   }
   return plainTypeName;
 }
 protected DetectedPropertyInfo analyzeForNodeElementType(Node node, String propertyName) {
   if (isPmCommentNestedProperty(propertyName) || isPmCommentMethodCall(propertyName)) {
     return null;
   }
   final DfLanguageGrammar grammar = getLanguageGrammar();
   DetectedPropertyInfo detected = null;
   for (int i = 0; i < node.getChildSize(); i++) {
     final Node childNode = node.getChild(i);
     if (childNode instanceof BindVariableNode) {
       final BindVariableNode bindNode = (BindVariableNode) childNode;
       final String expression = bindNode.getExpression();
       if (!isPmCommentEqualsCurrent(expression)) {
         continue;
       }
       if (isPmCommentNestedProperty(expression) || isPmCommentMethodCall(expression)) {
         continue;
       }
       // /*#current*/ here
       final String testValue = bindNode.getTestValue();
       if (testValue == null) {
         continue;
       }
       final String propertyType = derivePropertyTypeFromTestValue(testValue);
       final String propertyOption = derivePropertyOptionFromTestValue(testValue);
       if (Srl.is_NotNull_and_NotTrimmedEmpty(propertyType)) {
         detected = new DetectedPropertyInfo();
         final String generic = grammar.buildGenericOneClassHint(propertyType);
         detected.setPropertyType("List" + generic);
         detected.setPropertyOption(propertyOption);
       }
     } else if (childNode instanceof ForNode) {
       final ForNode nestedNode = (ForNode) childNode;
       final String expression = nestedNode.getExpression();
       if (!isPmCommentStartsWithCurrent(expression)) {
         continue;
       }
       // /*FOR #current.xxx*/ here
       final String nestedForPropName = substringPmCommentCurrentRear(expression);
       detected = analyzeForNodeElementType(nestedNode, nestedForPropName); // recursive call
       if (detected != null) {
         final String generic = grammar.buildGenericOneClassHint(detected.getPropertyType());
         detected.setPropertyType("List" + generic);
       }
     } else if (childNode instanceof ScopeNode) { // IF, Begin, First, ...
       detected = analyzeForNodeElementType(childNode, propertyName); // recursive call
     }
     if (detected != null) {
       break;
     }
   }
   if (detected == null) {
     return null;
   }
   return detected;
 }