/*
* Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.template.soy.error;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.template.soy.base.SourceLocation;
import com.google.template.soy.base.internal.SoyFileSupplier;
import java.io.BufferedReader;
import java.io.IOException;
/**
* Fetches a snippet of source code surrounding a given {@link SourceLocation}. The snippet is just
* for human consumption and doesn't necessarily correspond to any unit of Soy syntax.
*
* @author brndn@google.com (Brendan Linn)
*/
public final class SnippetFormatter {
private final ImmutableMap<String, SoyFileSupplier> filePathsToSuppliers;
public SnippetFormatter(ImmutableMap<String, SoyFileSupplier> filePathsToSuppliers) {
this.filePathsToSuppliers = checkNotNull(filePathsToSuppliers);
}
/**
* Returns a snippet of source code surrounding the given {@link SourceLocation}, or {@link
* Optional#absent()} if source code is unavailable. (This happens, for example, when anyone uses
* {@link SourceLocation#UNKNOWN}, which is why no one should use it.)
*/
Optional<String> getSnippet(SourceLocation sourceLocation) throws IOException {
// Try to find a snippet of source code associated with the exception and print it.
SoyFileSupplier supplier = filePathsToSuppliers.get(sourceLocation.getFilePath());
if (supplier == null) {
return Optional.absent();
}
String result;
try (BufferedReader reader = new BufferedReader(supplier.open())) {
// Line numbers are 1-indexed
for (int linenum = 1; linenum < sourceLocation.getBeginLine(); ++linenum) {
// Skip preceding lines
reader.readLine();
}
result = reader.readLine(); // returns null on EOF
}
return Optional.fromNullable(result);
}
}