blob: b1c3cda12c650b7c25daaaa0dbf270ea9f213c35 [file] [log] [blame]
// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.SourceFileEnvironment;
import com.android.tools.r8.SourceFileProvider;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
public class SourceFileTemplateProvider implements SourceFileProvider {
private static final char VARIABLE_PREFIX = '%';
private static final Map<String, SourceFileProvider> HANDLERS =
ImmutableMap.<String, SourceFileProvider>builder()
.put(var("MAP_ID"), SourceFileEnvironment::getMapId)
.put(var("MAP_HASH"), SourceFileEnvironment::getMapHash)
.build();
private static String var(String name) {
return VARIABLE_PREFIX + name;
}
private static int getMaxVariableLength() {
int max = 0;
for (String key : HANDLERS.keySet()) {
max = Math.max(max, key.length());
}
return max;
}
public static SourceFileProvider create(String template, DiagnosticsHandler handler) {
String cleaned = template;
for (String variable : HANDLERS.keySet()) {
// Maintain the same size as template so indexing remains valid for error reporting.
cleaned = cleaned.replace(variable, ' ' + variable.substring(1));
}
assert template.length() == cleaned.length();
int unhandled = cleaned.indexOf(VARIABLE_PREFIX);
if (unhandled >= 0) {
while (unhandled >= 0) {
int endIndex = Math.min(unhandled + getMaxVariableLength(), template.length());
String variablePrefix = template.substring(unhandled, endIndex);
handler.error(
new StringDiagnostic("Invalid template variable starting with " + variablePrefix));
unhandled = cleaned.indexOf(VARIABLE_PREFIX, unhandled + 1);
}
return null;
}
return new SourceFileTemplateProvider(template);
}
private final String template;
private String cachedValue = null;
private SourceFileTemplateProvider(String template) {
this.template = template;
}
@Override
public String get(SourceFileEnvironment environment) {
if (cachedValue == null) {
cachedValue = template;
HANDLERS.forEach(
(variable, getter) -> {
cachedValue = cachedValue.replace(variable, getter.get(environment));
});
}
return cachedValue;
}
}