Process the expressions found in the HTML template

@param exposedTypeGenerator Class generating the ExposedType
@param templateParserResult Result from the parsing of the HTML Template
492386
private void processTemplateExpressions(ComponentExposedTypeGenerator exposedTypeGenerator,
      TemplateParserResult templateParserResult) {
    for (TemplateExpression expression : templateParserResult.getExpressions()) {
      generateTemplateExpressionMethod(exposedTypeGenerator,
          expression,
          templateParserResult.getTemplateName());
    }

    // Declare methods in the component
    String templateMethods = templateParserResult.getExpressions()
        .stream()
        .map(expression -> "p." + expression.getId())
        .collect(Collectors.joining(", "));

    exposedTypeGenerator.getOptionsBuilder()
        .addStatement("options.registerTemplateMethods($L)", templateMethods);
  }
881311
private String processExpression(String expressionString) {
    expressionString = expressionString == null ? "" : expressionString.trim();
    if (expressionString.isEmpty()) {
      if (isAttributeBinding(currentAttribute)) {
        logger.error(
            "Empty expression in template property binding. If you want to pass an empty string then simply don't use binding: my-attribute=\"\"",
            currentAttribute.toString());
      } else if (isEventBinding(currentAttribute)) {
        logger.error("Empty expression in template event binding.",
            currentAttribute.toString());
      } else {
        return "";
      }
    }

    if (expressionString.startsWith("{")) {
      logger.error(
          "Object literal syntax are not supported yet in Vue GWT, please use map(e(\"key1\", myValue), e(\"key2\", myValue2 > 5)...) instead. The object returned by map() is a regular Javascript Object (JsObject) with the given key/values.",
          expressionString);
    }

    if (expressionString.startsWith("[")) {
      logger.error(
          "Array literal syntax are not supported yet in Vue GWT, please use array(myValue, myValue2 > 5...) instead. The object returned by array() is a regular Javascript Array (JsArray) with the given values.",
          expressionString);
    }

    if (shouldSkipExpressionProcessing(expressionString)) {
      return expressionString;
    }

    return processJavaExpression(expressionString).toTemplateString();
  }
370562
private void evaluateExpressions() throws JspException {
        /* 
         * Note: we don't check for type mismatches here; we assume
         * the expression evaluator will return the expected type
         * (by virtue of knowledge we give it about what that type is).
         * A ClassCastException here is truly unexpected, so we let it
         * propagate up.
         */

        xml = ExpressionUtil.evalNotNull(
                "transform", "xml", xml_, Object.class, this, pageContext);
        xmlSystemId = (String) ExpressionUtil.evalNotNull(
                "transform", "xmlSystemId", xmlSystemId_, String.class,
                this, pageContext);
        xslt = ExpressionUtil.evalNotNull(
                "transform", "xslt", xslt_, Object.class, this,
                pageContext);
        xsltSystemId = (String) ExpressionUtil.evalNotNull(
                "transform", "xsltSystemId", xsltSystemId_, String.class,
                this, pageContext);
        result = (Result) ExpressionUtil.evalNotNull(
                "transform", "result", result_, Result.class, this, pageContext);

    }
494744
protected void processReturnTypeOfMethodDeclaration( MethodDeclaration methodDeclaration,
                                                         MethodMetadata methodMetadata ) {
        Type type = methodDeclaration.getReturnType2();
        if (type.isPrimitiveType()) {
            methodMetadata.setReturnType(FieldMetadata.primitiveType(((PrimitiveType)type).getPrimitiveTypeCode().toString()));
        }
        if (type.isSimpleType()) {
            methodMetadata.setReturnType(FieldMetadata.simpleType(JavaMetadataUtil.getName(((SimpleType)type).getName())));
        }
    }
413569
@Override
  JSType resolveInternal(ErrorReporter reporter) {
    if (!getReferencedType().isUnknownType()) {
      // In some cases (e.g. typeof(ns) when the actual type is just a literal object), a NamedType
      // is created solely for the purpose of naming an already-known type. When that happens,
      // there's nothing to look up, so just resolve the referenced type.
      return super.resolveInternal(reporter);
    }

    // TODO(user): Investigate whether it is really necessary to keep two
    // different mechanisms for resolving named types, and if so, which order
    // makes more sense. Now, resolution via registry is first in order to
    // avoid triggering the warnings built into the resolution via properties.
    boolean resolved = resolveViaRegistry(reporter);
    if (!resolved) {
      resolveViaProperties(reporter);
    }

    if (detectInheritanceCycle()) {
      handleTypeCycle(reporter);
    }
    super.resolveInternal(reporter);
    finishPropertyContinuations();

    JSType result = getReferencedType();
    if (isSuccessfullyResolved()) {
      int numKeys = result.getTemplateTypeMap().numUnfilledTemplateKeys();
      if (result.isObjectType()
          && (templateTypes != null && !templateTypes.isEmpty())
          && numKeys > 0) {
        ImmutableList<JSType> typeArgs = this.templateTypes;

        // Ignore any extraneous type args
        // TODO(johnlenz): report an error
        if (numKeys < this.templateTypes.size()) {
          typeArgs = typeArgs.subList(0, numKeys);
        }

        result = registry.createTemplatizedType(result.toMaybeObjectType(), typeArgs);
        setReferencedType(result);
      }

      resolutionScope = null;
    }
    return result;
  }
1191933
public Expression parse(ExpressionIterator expressionIterator, @NonNull ParserToken token) throws ParseException {
      PrefixHandler handler = prefixHandlers.containsKey(token.type)
                              ? prefixHandlers.get(token.type)
                              : prefixSkipHandler;
      if (handler == null) {
         throw new ParseException("No PrefixHandler registered for token type " + token.type);
      }
      return handler.parse(expressionIterator, token);
   }
988120
private void processProps() {
    ElementFilter
        .fieldsIn(component.getEnclosedElements())
        .stream()
        .filter(field -> hasAnnotation(field, Prop.class))
        .forEach(field -> {
          String propName = field.getSimpleName().toString();
          Prop prop = field.getAnnotation(Prop.class);

          collectionFieldsValidator.validateComponentPropField(field);

          fieldsWithNameExposed.add(new ExposedField(propName, field.asType()));

          optionsBuilder.addStatement(
              "options.addJavaProp($S, $T.getFieldName(this, () -> this.$L = $L), $L, $S)",
              propName,
              VueGWTTools.class,
              propName,
              getFieldMarkingValueForType(field.asType()),
              prop.required(),
              prop.checkType() ? getNativeNameForJavaType(field.asType()) : null
          );
        });
  }
1007339
public TemplateModel parseStandalone(
            final ITemplateContext context, final String template, final Set<String> templateSelectors,
            final TemplateMode templateMode, final boolean useCache, final boolean failIfNotExists) {

        Validate.notNull(context, "Context cannot be null");
        Validate.notNull(template, "Template cannot be null");
        // templateSelectors CAN be null if we are going to render the entire template
        // templateMode CAN be null if we are going to use the mode specified by the template resolver
        // templateResolutionAttributes CAN be null


        final String ownerTemplate = context.getTemplateData().getTemplate();
        final Map<String,Object> templateResolutionAttributes = context.getTemplateResolutionAttributes();

        final Set<String> cleanTemplateSelectors;
        if (templateSelectors != null && !templateSelectors.isEmpty()) {
            Validate.containsNoEmpties(
                    templateSelectors, "If specified, the Template Selector set cannot contain any nulls or empties");
            if (templateSelectors.size() == 1) {
                cleanTemplateSelectors = Collections.singleton(templateSelectors.iterator().next());
            } else {
                // We will be using a TreeSet because we want the selectors to be ORDERED, so that comparison at the
                // equals(...) method works alright
                cleanTemplateSelectors = Collections.unmodifiableSet(new TreeSet<String>(templateSelectors));
            }
        } else {
            cleanTemplateSelectors = null;
        }


        final TemplateCacheKey cacheKey =
                useCache?
                        new TemplateCacheKey(
                                ownerTemplate,
                                template, cleanTemplateSelectors,
                                0, 0,
                                templateMode,
                                templateResolutionAttributes)
                        : null;

        /*
         * First look at the cache - it might be already cached
         */
        if (useCache && this.templateCache != null) {
            final TemplateModel cached =  this.templateCache.get(cacheKey);
            if (cached != null) {
                /*
                 * Just at the end, and importantly AFTER CACHING, check if we need to apply any pre-processors
                 * to this model before returning and letting the engine insert the model in any way it needs.
                 */
                return applyPreProcessorsIfNeeded(context, cached);
            }
        }


        /*
         * Resolve the template
         */
        final TemplateResolution templateResolution =
                resolveTemplate(this.configuration, ownerTemplate, template, templateResolutionAttributes, failIfNotExists);


        /*
         * Once the template has been resolved (or tried to), and depending on the value of our 'failIfNotExists'
         * flag, we will check two conditions in which we will be returning null:
         *
         *    1. No template resolver has been able to resolve the template (this can happen if resolvers are
         *       configured with the 'checkExistence' flag to true).
         *    2. If the template was resolved, its existence should be checked in order to avoid exceptions during
         *       the reading phase.
         *
         * NOTE we will not cache this "null" result because the fact that a template is cacheable or not is
         * determined by template resolvers. And in this case there is no template resolver being applied
         * (actually, we are here because no resolver had success).
         */
        if (!failIfNotExists) {

            if (templateResolution == null) {
                // No resolver could resolve this
                return null;
            }

            if (!templateResolution.isTemplateResourceExistenceVerified()) {
                final ITemplateResource resource = templateResolution.getTemplateResource();
                if (resource == null || !resource.exists()) {
                    // Calling resource.exists() each time is not great, but think this only happens if the resource
                    // has not been cached (e.g. when it does not exist)
                    return null;
                }
            }

        }


        /*
         * Build the TemplateData object
         */
        final TemplateData templateData =
                buildTemplateData(templateResolution, template, cleanTemplateSelectors, templateMode, useCache);


        /*
         *  Create the Template Handler that will be in charge of building the TemplateModel
         */
        final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);


        /*
         * PROCESS THE TEMPLATE
         */
        final ITemplateParser parser = getParserForTemplateMode(templateData.getTemplateMode());
        parser.parseStandalone(
                this.configuration,
                ownerTemplate, template, cleanTemplateSelectors, templateData.getTemplateResource(),
                templateData.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler);

        final TemplateModel templateModel = builderHandler.getModel();


        /*
         * Cache the template if it is cacheable
         */
        if (useCache && this.templateCache != null) {
            if (templateResolution.getValidity().isCacheable()) {
                this.templateCache.put(cacheKey, templateModel);
            }
        }


        /*
         * Last step: just at the end, and importantly AFTER CACHING, check if we need to apply any pre-processors
         * to this model before returning and letting the engine insert the model in any way it needs.
         */
        return applyPreProcessorsIfNeeded(context, templateModel);

    }
103318
private Object processParam(TemplateParam<?, ?, ?> param, Map<String, Object> params, Template<?> template) {
		Object value = fetchParamValue(param, params, param.getFetcher());
		value = convertParamValue(value, param.getType(), param.getConverter());
		validateParamValue(value, param.getValidator());
		return value;
	}
359509
private void checkValueType(TemplateParam param, SoyValue value, TemplateNode node) {
    if (!TofuTypeChecks.isInstance(param.type(), value, node.getSourceLocation())) {
      // should this be a soydataexception?
      throw RenderException.createWithSource(
          "Parameter type mismatch: attempt to bind value '"
              + (value instanceof UndefinedData ? "(undefined)" : value)
              + "' (a "
              + value.getClass().getSimpleName()
              + ") to parameter '"
              + param.name()
              + "' which has a declared type of '"
              + param.type()
              + "'.",
          node);
    }
  }
1261580
private void processFunction(final Expression expression, final FunctionDescriptor od, RulesTextProvider textProvider) throws ParserException
	{
    	log.debug("processFunction");
		if (!exact("(",textProvider))
			throw new ParserException("Expected ')' after '"+od.getName()+"': ",textProvider);
		Class<?> args[] = od.getParameterTypes();
		for (int arg=1;arg <= args.length;arg++)
		{
			if (args[arg-1].equals(Expression.class))
			{
				Expression e = processExpression(textProvider);
				expression.expression(e);
			}
			if (args[arg-1].equals(List.class))
			{	
				if (!xpath(textProvider))
					throw new ParserException("expected list operand: ",textProvider);
				// operand string found
				String operand = textProvider.getLastToken();
				if (!textProvider.findOperandInScope(operand))
				{
					throw new ParserException("Could not locate "+operand+" in scope",textProvider);
				}
				expression.list(textProvider.getLastToken(),textProvider.getLastResolvedField());
			}
			else
			{
	             Expression e = processExpression(textProvider);
	             expression.expression(e);
			}
			if (arg < args.length)
			{
				// ensure arguments are separated by a comma
			    exactOrError(",",textProvider);
			}
		}
		exactOrError(")",textProvider);
		expression.function(od);
	}
683259
private void evaluateExpressions() throws JspException {
        /* 
         * Note: we don't check for type mismatches here; we assume
         * the expression evaluator will return the expected type
         * (by virtue of knowledge we give it about what that type is).
         * A ClassCastException here is truly unexpected, so we let it
         * propagate up.
         */

        xml = ExpressionUtil.evalNotNull(
                "parse", "xml", xml_, Object.class, this, pageContext);
        systemId = (String) ExpressionUtil.evalNotNull(
                "parse", "systemId", systemId_, String.class, this, pageContext);

        try {
            filter = (XMLFilter) ExpressionUtil.evalNotNull(
                    "parse", "filter", filter_, XMLFilter.class, this, pageContext);
        } catch (NullAttributeException ex) {
            // explicitly let 'filter' be null
            filter = null;
        }
    }
1322573
@Override
    protected boolean onProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        List<TypeElement> deferredTypes = deferredTypeNames.stream()
                .map(deferred -> processingEnv.getElementUtils().getTypeElement(deferred)).collect(Collectors.toList());

        if (roundEnv.processingOver()) {
            // This means that the previous round didn't generate any new sources, so we can't have found
            // any new instances of @Templated; and we can't have any new types that are the reason a type
            // was in deferredTypes.
            for (TypeElement type : deferredTypes) {
                error(type, "Did not generate @%s class for %s because it references undefined types",
                        Templated.class.getSimpleName(), type);
            }
            return false;
        }

        Collection<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(Templated.class);
        List<TypeElement> types = new ImmutableList.Builder<TypeElement>()
                .addAll(deferredTypes)
                .addAll(ElementFilter.typesIn(annotatedElements))
                .build();
        deferredTypeNames.clear();
        for (TypeElement type : types) {
            try {
                Templated templated = type.getAnnotation(Templated.class);
                validateType(type, templated);

                boolean isInjectable = templated.injectable() == Injectable.TRUE
                        || (templated.injectable() == Injectable.IF_DI_DETECTED && diInClasspath());
                processType(type, templated, isInjectable ? "@javax.inject.Inject" : "");
            } catch (AbortProcessingException e) {
                // We abandoned this type; continue with the next.
            } catch (MissingTypeException e) {
                // We abandoned this type, but only because we needed another type that it references and
                // that other type was missing. It is possible that the missing type will be generated by
                // further annotation processing, so we will try again on the next round (perhaps failing
                // again and adding it back to the list). We save the name of the @Templated type rather
                // than its TypeElement because it is not guaranteed that it will be represented by
                // the same TypeElement on the next round.
                deferredTypeNames.add(type.getQualifiedName().toString());
            } catch (RuntimeException e) {
                // Don't propagate this exception, which will confusingly crash the compiler.
                // Instead, report a compiler error with the stack trace.
                String trace = Throwables.getStackTraceAsString(e);
                error(type, "@%s processor threw an exception: %s", Templated.class.getSimpleName(), trace);
            }
        }
        return false;  // never claim annotation, because who knows what other processors want?
    }
631711
private static void generateParserOnXmlEndElement(BindTypeContext context, MethodSpec.Builder methodBuilder,
			String instanceName, String parserName, BindEntity entity) {
		methodBuilder.beginControlFlow("if (elementName.equals($L.getName()))", parserName);
		methodBuilder.addStatement("currentTag = elementName");
		methodBuilder.addStatement("elementName = null");
		methodBuilder.endControlFlow();

	}
335947
private void generateGetStaticRenderFunctions(ComponentExposedTypeGenerator exposedTypeGenerator,
      VueTemplateCompilerResult result) {
    CodeBlock.Builder staticFunctions = CodeBlock.builder();

    boolean isFirst = true;
    for (String staticRenderFunction : result.getStaticRenderFunctions()) {
      if (!isFirst) {
        staticFunctions.add(", ");
      } else {
        isFirst = false;
      }

      staticFunctions.add("new $T($S)", Function.class, staticRenderFunction);
    }

    MethodSpec.Builder getStaticRenderFunctionsBuilder = MethodSpec
        .methodBuilder("getStaticRenderFunctions")
        .addModifiers(Modifier.PRIVATE)
        .returns(Function[].class)
        .addStatement("return new $T[] { $L }", Function.class, staticFunctions.build());

    exposedTypeGenerator.getClassBuilder().addMethod(getStaticRenderFunctionsBuilder.build());
  }
1007951
private static void generateParserOnXmlStartElement(BindTypeContext context, MethodSpec.Builder methodBuilder,
			String instanceName, String parserName, BindEntity entity) {
		BindTransform bindTransform;
		// start and inner bean
		methodBuilder.addStatement("currentTag = xmlParser.getName().toString()");

		int count = 0;
		// count property to manage
		{
			// for each elements
			for (BindProperty property : entity.getCollection()) {
				if (property.xmlInfo.xmlType != XmlType.TAG)
					continue;

				bindTransform = BindTransformer.lookup(property);

				// here we manage only property of bean type
				if (bindTransform != null) {
					count++;
				}
			}
		}

		if (count > 0) {
			// switch for tag elements
			// @formatter:off
			methodBuilder.beginControlFlow("switch(currentTag)$>");

			// for each elements
			for (BindProperty property : entity.getCollection()) {
				if (property.xmlInfo.xmlType != XmlType.TAG)
					continue;

				bindTransform = BindTransformer.lookup(property);

				// here we manage only property of bean type
				if (bindTransform != null) {
					methodBuilder.addCode("case $S:\n$>", BindProperty.xmlName(property));
					methodBuilder.addCode("// property $L (mapped on $S)\n", property.getName(),
							BindProperty.xmlName(property));

					// methodBuilder.beginControlFlow("if
					// (!xmlParser.isEmptyElement())");
					bindTransform.generateParseOnXml(context, methodBuilder, "xmlParser",
							property.getPropertyType().getTypeName(), "instance", property);
					// methodBuilder.endControlFlow();

					methodBuilder.addStatement("$<break");
				}
			}

			methodBuilder.addCode("default:\n$>");
			// methodBuilder.addStatement("$L.skipElement()", parserName);

			methodBuilder.addStatement("$<break");
			methodBuilder.endControlFlow();
		} else {
			methodBuilder.addCode("// No property to manage here\n");
		}
		// @formatter:on

	}
677999
private void resolveTypeTemplates() {
        Collections.sort(context.getClassesAlreadyDone(), new Comparator<Java4CppType>() {

            @Override
            public int compare(Java4CppType t1, Java4CppType t2) {
                Class<?> o1 = t1.getRawClass();
                Class<?> o2 = t2.getRawClass();
                if (o1.isArray() && o2.isArray()) {
                    int idx1 = o1.getName().lastIndexOf('[');
                    int idx2 = o2.getName().lastIndexOf('[');
                    if (idx1 == idx2) {
                        return o1.getName().compareTo(o2.getName());
                    }
                    return idx1 < idx2 ? -1 : 1;
                } else if (o1.isArray() && !o2.isArray()) {
                    return 1;
                } else if (!o1.isArray() && o2.isArray()) {
                    return -1;
                }
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (Java4CppType type : context.getClassesAlreadyDone()) {
            context.executeTypeTemplate(type);
        }
    }