pebble icon indicating copy to clipboard operation
pebble copied to clipboard

can't use Java 11 var api with evaluate

Open xenoterracide opened this issue 5 years ago • 3 comments

this does not compile

    var writer = new StringWriter();

    var tmpl = engine.getTemplate( "TestApplication.java.pbl" );
    tmpl.evaluate( writer, context ); // fails here due to map being `Map<String, String>`

probably better to make the inbound map value type generic, e.g

  <T> void evaluate( Map<String, T> context ) {
  }

here's the full class, if it helps

/* Copyright © 2020 Caleb Cushing. All rights reserved */
package com.xenoterracide.scaf;

import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.loader.FileLoader;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import picocli.CommandLine;

import java.io.StringWriter;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

@CommandLine.Command(name = "skaf")
public final class Application implements Runnable {

  @Nullable
  @CommandLine.Parameters(index = "0", description = "first configuration directory")
  private String arg;

  @CommandLine.Parameters(
    index = "1..*",
    description = "path to configuration directories separated by space"
  )
  private List<String> args = List.of();

  @CommandLine.Option(names = { "-d", "--dir" }, description = "path to scaf directory")
  private Path dir = Path.of(".scaf");

  @CommandLine.Option(names = "--template-dir", description = "template directory")
  private Path templateDir = dir.resolve("templates");

  /*
  @CommandLine.Option( names = "--config-dir", description = "config directory" )
  private Path configDir = dir.resolve( "config" );

   */

  private final FileLoader loader = new FileLoader();

  private final PebbleEngine engine = new PebbleEngine.Builder()
    .newLineTrimming( false )
    .strictVariables( true )
    .loader( loader )
    .build();

  @Override
  public void run() {
    if (arg == null) {
      throw new IllegalStateException("impossible!");
    }
    loader.setPrefix( templateDir.toString() );

    var name = args.remove( args.size() -1 );
    var context = Map.of("name", name);
    
    var writer = new StringWriter();

    var tmpl = engine.getTemplate( "TestApplication.java.pbl" );
    tmpl.evaluate( writer, context ); // fails here due to map being `Map<String, String>`
  }

  public static void main(@NonNull String... args) {
    var cli = new CommandLine(new Application());
    System.exit(cli.execute(args));
  }
}

xenoterracide avatar Nov 28 '20 18:11 xenoterracide

It is possible to tell the compiler to use it as a <String, Object> by doing Map<String, Object> context = Map.of("name", name);.

ogrammer avatar Dec 11 '20 16:12 ogrammer

right, but couldn't PebbleTemplate.getTemplate take a generic based on the input? e.g <T> Map<String, T>.

HashMap<String, Object> context = Map.of("name", name);

is the returned a HashMap? I could check but I think it just returns Map and that Map is immutable, I think. Still I am doing Map<String, Object> here, that was my workaround, I just think if it took a generic one wouldn't have to workaround it.

xenoterracide avatar Dec 11 '20 17:12 xenoterracide

Apologies, I used a Map when testing it but as I use HashMap all the time I automatically wrote it as HashMap in my answer. And your idea seems nice, maybe make a pull request? Doesn't sound too hard.

ogrammer avatar Dec 11 '20 21:12 ogrammer