blob: 50ff3a1d31800d6f8fcc006f3c1208664024b072 [file] [log] [blame]
// Copyright (c) 2017, 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.naming;
import static com.android.tools.r8.position.TextPosition.UNKNOWN_COLUMN;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.position.TextPosition;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
public class DictionaryReader implements AutoCloseable {
private final BufferedReader reader;
private final Path path;
public DictionaryReader(Path path) throws IOException {
this.path = path;
this.reader = Files.newBufferedReader(path);
}
public String readName(Reporter reporter) throws IOException {
assert reader != null;
StringBuilder name = new StringBuilder();
int readCharAsInt;
int lineNumber = 1;
while ((readCharAsInt = reader.read()) != -1) {
char readChar = (char) readCharAsInt;
if ((name.length() != 0 && Character.isJavaIdentifierPart(readChar))
|| (name.length() == 0 && Character.isJavaIdentifierStart(readChar))) {
name.append(readChar);
} else {
boolean isCommentChar = readChar == '#';
boolean isValidEndOfLineInput = readChar == '\n' || readChar == '\r';
if (isCommentChar || isValidEndOfLineInput) {
if (isCommentChar) {
reader.readLine();
}
lineNumber++;
}
if (isValidEndOfLineInput && name.length() != 0) {
return name.toString();
}
name = new StringBuilder();
// An illegal character was in the input. We discard the entire line instead of returning as
// much as possible, to ensure us not throwing an error in the case of duplicates.
if (!isValidEndOfLineInput) {
reporter.info(
new StringDiagnostic(
"Invalid character in dictionary '" + readChar + "'",
new PathOrigin(path),
new TextPosition(0, lineNumber, UNKNOWN_COLUMN)));
reader.readLine();
lineNumber++;
}
}
}
return name.toString();
}
@Override
public void close() throws IOException {
if (reader != null) {
reader.close();
}
}
public static ImmutableList<String> readAllNames(Path path, Reporter reporter) {
if (path != null) {
Set<String> seenNames = new HashSet<>();
Builder<String> namesBuilder = new ImmutableList.Builder<String>();
try (DictionaryReader reader = new DictionaryReader(path);) {
String name = reader.readName(reporter);
while (!name.isEmpty()) {
if (!seenNames.add(name)) {
reporter.error(
new StringDiagnostic(
"Duplicate entry for '" + name + "' in dictionary", new PathOrigin(path)));
}
namesBuilder.add(name);
name = reader.readName(reporter);
}
} catch (IOException e) {
reporter.error(new ExceptionDiagnostic(e, new PathOrigin(path)));
}
return namesBuilder.build();
} else {
return ImmutableList.of();
}
}
}