do not exit repl if something went wrong
This commit is contained in:
+34
-20
@@ -18,8 +18,8 @@ package org.jetbrains.jet.cli.common.messages;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiErrorElement;
|
||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
|
||||
import jet.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -75,8 +75,8 @@ public final class AnalyzerWithCompilerReport {
|
||||
};
|
||||
}
|
||||
|
||||
private void reportDiagnostic(@NotNull Diagnostic diagnostic) {
|
||||
if (!diagnostic.isValid()) return;
|
||||
private static boolean reportDiagnostic(@NotNull Diagnostic diagnostic, @NotNull MessageCollector messageCollector) {
|
||||
if (!diagnostic.isValid()) return false;
|
||||
DiagnosticUtils.LineAndColumn lineAndColumn = DiagnosticUtils.getLineAndColumn(diagnostic);
|
||||
VirtualFile virtualFile = diagnostic.getPsiFile().getVirtualFile();
|
||||
String path = virtualFile == null ? null : virtualFile.getPath();
|
||||
@@ -87,8 +87,9 @@ public final class AnalyzerWithCompilerReport {
|
||||
else {
|
||||
render = DefaultErrorMessages.RENDERER.render(diagnostic);
|
||||
}
|
||||
messageCollectorWrapper.report(convertSeverity(diagnostic.getSeverity()), render,
|
||||
CompilerMessageLocation.create(path, lineAndColumn.getLine(), lineAndColumn.getColumn()));
|
||||
messageCollector.report(convertSeverity(diagnostic.getSeverity()), render,
|
||||
CompilerMessageLocation.create(path, lineAndColumn.getLine(), lineAndColumn.getColumn()));
|
||||
return diagnostic.getSeverity() == Severity.ERROR;
|
||||
}
|
||||
|
||||
private void reportIncompleteHierarchies() {
|
||||
@@ -104,27 +105,40 @@ public final class AnalyzerWithCompilerReport {
|
||||
}
|
||||
}
|
||||
|
||||
private void reportDiagnostics() {
|
||||
assert analyzeExhaust != null;
|
||||
for (Diagnostic diagnostic : analyzeExhaust.getBindingContext().getDiagnostics()) {
|
||||
reportDiagnostic(diagnostic);
|
||||
public static boolean reportDiagnostics(@NotNull BindingContext bindingContext, @NotNull MessageCollector messageCollector) {
|
||||
boolean hasErrors = false;
|
||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||
hasErrors |= reportDiagnostic(diagnostic, messageCollector);
|
||||
}
|
||||
return hasErrors;
|
||||
}
|
||||
|
||||
private void reportSyntaxErrors(@NotNull Collection<JetFile> files) {
|
||||
for (JetFile file : files) {
|
||||
file.accept(new AnalyzingUtils.PsiErrorElementVisitor() {
|
||||
@Override
|
||||
public void visitErrorElement(PsiErrorElement element) {
|
||||
String description = element.getErrorDescription();
|
||||
String message = StringUtil.isEmpty(description) ? "Syntax error" : description;
|
||||
Diagnostic diagnostic = new SyntaxErrorDiagnostic(element, Severity.ERROR, message);
|
||||
reportDiagnostic(diagnostic);
|
||||
}
|
||||
});
|
||||
for (PsiElement file : files) {
|
||||
reportSyntaxErrors(file, AnalyzerWithCompilerReport.this.messageCollectorWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean reportSyntaxErrors(@NotNull PsiElement file, @NotNull final MessageCollector messageCollector) {
|
||||
class ErrorReportingVisitor extends AnalyzingUtils.PsiErrorElementVisitor {
|
||||
boolean hasErrors = false;
|
||||
|
||||
@Override
|
||||
public void visitErrorElement(PsiErrorElement element) {
|
||||
String description = element.getErrorDescription();
|
||||
String message = StringUtil.isEmpty(description) ? "Syntax error" : description;
|
||||
Diagnostic diagnostic = new SyntaxErrorDiagnostic(element, Severity.ERROR, message);
|
||||
reportDiagnostic(diagnostic, messageCollector);
|
||||
hasErrors = true;
|
||||
}
|
||||
}
|
||||
ErrorReportingVisitor visitor = new ErrorReportingVisitor();
|
||||
|
||||
file.accept(visitor);
|
||||
|
||||
return visitor.hasErrors;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AnalyzeExhaust getAnalyzeExhaust() {
|
||||
return analyzeExhaust;
|
||||
@@ -137,7 +151,7 @@ public final class AnalyzerWithCompilerReport {
|
||||
public void analyzeAndReport(@NotNull Function0<AnalyzeExhaust> analyzer, @NotNull Collection<JetFile> files) {
|
||||
reportSyntaxErrors(files);
|
||||
analyzeExhaust = analyzer.invoke();
|
||||
reportDiagnostics();
|
||||
reportDiagnostics(analyzeExhaust.getBindingContext(), messageCollectorWrapper);
|
||||
reportIncompleteHierarchies();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,7 @@ package org.jetbrains.jet.cli.common.messages;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface MessageCollector {
|
||||
MessageCollector PLAIN_TEXT_TO_SYSTEM_ERR = new MessageCollector() {
|
||||
@Override
|
||||
public void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location) {
|
||||
System.err.println(MessageRenderer.PLAIN.render(severity, message, location));
|
||||
}
|
||||
};
|
||||
MessageCollector PLAIN_TEXT_TO_SYSTEM_ERR = new MessageCollectorPlainTextToStream(System.err);
|
||||
|
||||
void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location);
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.jet.cli.common.messages;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class MessageCollectorPlainTextToStream implements MessageCollector {
|
||||
@NotNull
|
||||
private final PrintStream stream;
|
||||
|
||||
public MessageCollectorPlainTextToStream(@NotNull PrintStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location) {
|
||||
stream.println(MessageRenderer.PLAIN.render(severity, message, location));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.jet.cli.common.messages;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class MessageCollectorToString implements MessageCollector {
|
||||
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
private final MessageCollector actualCollector = new MessageCollectorPlainTextToStream(new PrintStream(outputStream));
|
||||
|
||||
|
||||
@Override
|
||||
public void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location) {
|
||||
actualCollector.report(severity, message, location);
|
||||
}
|
||||
|
||||
private static Charset UTF8 = Charset.forName("utf-8");
|
||||
|
||||
@NotNull
|
||||
public String getString() {
|
||||
return UTF8.decode(ByteBuffer.wrap(outputStream.toByteArray())).toString();
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,10 @@ public class ReplFromTerminal {
|
||||
}
|
||||
|
||||
ReplInterpreter.LineResult lineResult = getReplInterpreter().eval(line);
|
||||
if (!lineResult.isUnit()) {
|
||||
if (!lineResult.isSuccessful()) {
|
||||
System.out.print(lineResult.getErrorText());
|
||||
}
|
||||
else if (!lineResult.isUnit()) {
|
||||
System.out.println(lineResult.getValue());
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.jet.cli.jvm.repl;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -29,6 +30,9 @@ import com.intellij.testFramework.LightVirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport;
|
||||
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.jet.cli.common.messages.MessageCollectorToString;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactories;
|
||||
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||
@@ -40,7 +44,6 @@ import org.jetbrains.jet.lang.descriptors.NamespaceLikeBuilderDummy;
|
||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver;
|
||||
@@ -60,7 +63,6 @@ import org.jetbrains.jet.utils.ExceptionUtils;
|
||||
import org.jetbrains.jet.utils.Progress;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -122,19 +124,52 @@ public class ReplInterpreter {
|
||||
public static class LineResult {
|
||||
private final Object value;
|
||||
private final boolean unit;
|
||||
private final String errorText;
|
||||
|
||||
public LineResult(Object value, boolean unit) {
|
||||
private LineResult(Object value, boolean unit, String errorText) {
|
||||
this.value = value;
|
||||
this.unit = unit;
|
||||
this.errorText = errorText;
|
||||
}
|
||||
|
||||
public boolean isSuccessful() {
|
||||
return errorText == null;
|
||||
}
|
||||
|
||||
private void checkSuccessful() {
|
||||
if (!isSuccessful()) {
|
||||
throw new IllegalStateException("it is error");
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
checkSuccessful();
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isUnit() {
|
||||
checkSuccessful();
|
||||
return unit;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getErrorText() {
|
||||
return errorText;
|
||||
}
|
||||
|
||||
public static LineResult successful(Object value, boolean unit) {
|
||||
return new LineResult(value, unit, null);
|
||||
}
|
||||
|
||||
public static LineResult error(@NotNull String errorText) {
|
||||
if (errorText.isEmpty()) {
|
||||
errorText = "<unknown error>";
|
||||
}
|
||||
else if (!errorText.endsWith("\n")) {
|
||||
errorText = errorText + "\n";
|
||||
}
|
||||
return new LineResult(null, false, errorText);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -147,13 +182,21 @@ public class ReplInterpreter {
|
||||
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
|
||||
JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false);
|
||||
|
||||
AnalyzingUtils.checkForSyntacticErrors(psiFile);
|
||||
MessageCollectorToString errorCollector = new MessageCollectorToString();
|
||||
|
||||
boolean hasErrors = AnalyzerWithCompilerReport.reportSyntaxErrors(psiFile, errorCollector);
|
||||
if (hasErrors) {
|
||||
return LineResult.error(errorCollector.getString());
|
||||
}
|
||||
|
||||
injector.getTopDownAnalyzer().prepareForTheNextReplLine();
|
||||
|
||||
psiFile.getScript().putUserData(ScriptHeaderResolver.PRIORITY_KEY, lineNumber);
|
||||
|
||||
ScriptDescriptor scriptDescriptor = doAnalyze(psiFile);
|
||||
ScriptDescriptor scriptDescriptor = doAnalyze(psiFile, errorCollector);
|
||||
if (scriptDescriptor == null) {
|
||||
return LineResult.error(errorCollector.getString());
|
||||
}
|
||||
|
||||
Progress backendProgress = new Progress() {
|
||||
@Override
|
||||
@@ -188,14 +231,19 @@ public class ReplInterpreter {
|
||||
}
|
||||
|
||||
Constructor<?> scriptInstanceConstructor = scriptClass.getConstructor(constructorParams);
|
||||
Object scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs);
|
||||
Object scriptInstance;
|
||||
try {
|
||||
scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs);
|
||||
} catch (Throwable e) {
|
||||
return LineResult.error(Throwables.getStackTraceAsString(e));
|
||||
}
|
||||
Field rvField = scriptClass.getDeclaredField("rv");
|
||||
rvField.setAccessible(true);
|
||||
Object rv = rvField.get(scriptInstance);
|
||||
|
||||
earlierLines.add(new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance, scriptClassName));
|
||||
|
||||
return new LineResult(rv, scriptDescriptor.getReturnType().equals(JetStandardClasses.getUnitType()));
|
||||
return LineResult.successful(rv, scriptDescriptor.getReturnType().equals(JetStandardClasses.getUnitType()));
|
||||
} catch (Throwable e) {
|
||||
PrintWriter writer = new PrintWriter(System.err);
|
||||
classLoader.dumpClasses(writer);
|
||||
@@ -204,7 +252,8 @@ public class ReplInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
private ScriptDescriptor doAnalyze(@NotNull JetFile psiFile) {
|
||||
@Nullable
|
||||
private ScriptDescriptor doAnalyze(@NotNull JetFile psiFile, @NotNull MessageCollector messageCollector) {
|
||||
final WritableScope scope = new WritableScopeImpl(
|
||||
JetScope.EMPTY, module,
|
||||
new TraceBasedRedeclarationHandler(trace), "Root scope in analyzeNamespace");
|
||||
@@ -231,8 +280,10 @@ public class ReplInterpreter {
|
||||
// namespaces added to module explicitly in
|
||||
injector.getTopDownAnalyzer().doProcess(scope, new NamespaceLikeBuilderDummy(), Collections.singletonList(psiFile));
|
||||
|
||||
// TODO: print, not throw
|
||||
AnalyzingUtils.throwExceptionOnErrors(trace.getBindingContext());
|
||||
boolean hasErrors = AnalyzerWithCompilerReport.reportDiagnostics(trace.getBindingContext(), messageCollector);
|
||||
if (hasErrors) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ScriptDescriptor scriptDescriptor = injector.getTopDownAnalysisContext().getScripts().get(psiFile.getScript());
|
||||
lastLineScope = trace.get(BindingContext.SCRIPT_SCOPE, scriptDescriptor);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
>>> fun foo() = 765
|
||||
null
|
||||
>>> foo(1)
|
||||
ERROR: /line2.ktscript: (1, 5) Too many arguments for internal final fun foo() : jet.Int defined in <script>
|
||||
>>> foo()
|
||||
765
|
||||
@@ -0,0 +1,6 @@
|
||||
>>> throw Exception("hi there")
|
||||
stack trace
|
||||
>>> fun foo() = 2
|
||||
null
|
||||
>>> foo()
|
||||
2
|
||||
@@ -58,10 +58,17 @@ public class ReplInterpreterTest {
|
||||
ReplSessionTestFile file = ReplSessionTestFile.load(new File("compiler/testData/repl/" + relativePath));
|
||||
for (Pair<String, String> t : file.getLines()) {
|
||||
String code = t.first;
|
||||
String expected = t.second;
|
||||
String expected = t.second.replaceFirst("\r?\n$", "");
|
||||
|
||||
Object actual = repl.eval(code).getValue();
|
||||
String actualString = actual != null ? actual.toString() : "null";
|
||||
ReplInterpreter.LineResult lineResult = repl.eval(code);
|
||||
Object actual;
|
||||
if (lineResult.isSuccessful()) {
|
||||
actual = lineResult.getValue();
|
||||
}
|
||||
else {
|
||||
actual = lineResult.getErrorText();
|
||||
}
|
||||
String actualString = (actual != null ? actual.toString() : "null").replaceFirst("\r?\n$", "");
|
||||
|
||||
Assert.assertEquals("after evaluation of: " + code, expected, actualString);
|
||||
}
|
||||
@@ -113,4 +120,22 @@ public class ReplInterpreterTest {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void syntaxErrors() {
|
||||
testFile("syntaxErrors.repl");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void analyzeErrors() {
|
||||
// TODO
|
||||
//testFile("analyzeErrors.repl");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evaluationErrors() {
|
||||
// TODO
|
||||
//testFile("evaluationErrors.repl");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package org.jetbrains.jet.repl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -51,7 +53,8 @@ public class ReplSessionTestFile {
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
|
||||
return load(reader);
|
||||
List<String> lines = CharStreams.readLines(reader);
|
||||
return load(new SimpleLinesParser(lines));
|
||||
} finally {
|
||||
inputStream.close();
|
||||
}
|
||||
@@ -60,28 +63,22 @@ public class ReplSessionTestFile {
|
||||
}
|
||||
}
|
||||
|
||||
private static ReplSessionTestFile load(@NotNull BufferedReader reader) throws IOException {
|
||||
private static ReplSessionTestFile load(@NotNull SimpleLinesParser parser) throws IOException {
|
||||
List<Pair<String, String>> list = Lists.newArrayList();
|
||||
while (true) {
|
||||
String odd = reader.readLine();
|
||||
if (odd == null) {
|
||||
return new ReplSessionTestFile(list);
|
||||
}
|
||||
|
||||
Pattern pattern = Pattern.compile(">>>( |$)(.*)");
|
||||
Matcher matcher = pattern.matcher(odd);
|
||||
if (!matcher.matches()) {
|
||||
throw new IllegalStateException("odd lines must start with >>>");
|
||||
}
|
||||
while (!parser.lookingAtEof()) {
|
||||
Pattern startPattern = Pattern.compile(">>>( |$)(.*)");
|
||||
Matcher matcher = parser.next(startPattern);
|
||||
String code = matcher.group(2);
|
||||
|
||||
String even = reader.readLine();
|
||||
if (even == null) {
|
||||
throw new IllegalStateException("expecting even");
|
||||
StringBuilder value = new StringBuilder();
|
||||
|
||||
while (!parser.lookingAtEof() && parser.lookingAt(startPattern) == null) {
|
||||
value.append(parser.next()).append("\n");
|
||||
}
|
||||
|
||||
list.add(Pair.create(code, even));
|
||||
list.add(Pair.create(code, value.toString()));
|
||||
}
|
||||
return new ReplSessionTestFile(list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.jet.repl;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*
|
||||
* @see org.jetbrains.jet.lang.types.ref.SimpleParser
|
||||
*/
|
||||
class SimpleLinesParser {
|
||||
|
||||
@NotNull
|
||||
private final List<String> lines;
|
||||
private int position;
|
||||
|
||||
SimpleLinesParser(@NotNull List<String> lines) {
|
||||
this.lines = lines;
|
||||
}
|
||||
|
||||
public boolean lookingAtEof() {
|
||||
return position == lines.size();
|
||||
}
|
||||
|
||||
public void checkNotEof() {
|
||||
if (lookingAtEof()) {
|
||||
throw new IllegalStateException("unexpected EOF");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String lookahead() {
|
||||
checkNotEof();
|
||||
return lines.get(position);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Matcher lookingAt(@NotNull Pattern pattern) {
|
||||
if (lookingAtEof()) {
|
||||
return null;
|
||||
}
|
||||
Matcher matcher = pattern.matcher(lookahead());
|
||||
if (matcher.matches()) {
|
||||
return matcher;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Matcher next(@NotNull Pattern pattern) {
|
||||
Matcher r = lookingAt(pattern);
|
||||
if (r == null) {
|
||||
throw new IllegalStateException("line " + position + " must match " + pattern);
|
||||
}
|
||||
++position;
|
||||
return r;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String next() {
|
||||
String r = lookahead();
|
||||
++position;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user