Skip to content

Commit

Permalink
Merge pull request #48 from spoofax-shell/resolve-fixmes-todos
Browse files Browse the repository at this point in the history
[RDY] Resolve FIXMEs and TODOs
  • Loading branch information
gfokkema authored Jun 17, 2016
2 parents df954f1 + dc9a40d commit 4c8302f
Show file tree
Hide file tree
Showing 60 changed files with 341 additions and 241 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.metaborg.spoofax.shell.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

Expand All @@ -12,10 +11,8 @@
import org.metaborg.spoofax.shell.client.console.impl.history.JLine2PersistentInputHistory;
import org.metaborg.spoofax.shell.commands.IReplCommand;

import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

/**
Expand Down Expand Up @@ -54,24 +51,4 @@ protected void configure() {
super.configure();
bindUserInterface();
}

/**
* TODO: Replace with "CheckedProvides" because IO in Provider method is bad practice, see:
* https://github.com/google/guice/wiki/ThrowingProviders.
*
* @param in
* The {@link InputStream}.
* @param out
* The {@link OutputStream}.
* @return A {@link jline.console.ConsoleReader} with the given streams.
* @throws IOException
* When an IO error occurs upon construction.
*/
@Provides
@Singleton
protected jline.console.ConsoleReader provideConsoleReader(@Named("in") InputStream in,
@Named("out") OutputStream out)
throws IOException {
return new jline.console.ConsoleReader(in, out);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,30 @@
* This class launches a {@link ConsoleRepl}, a console based REPL.
*/
public final class Main {
private static final String ERROR = "Invalid commandline parameters: %s%nThe only argument "
+ "accepted is the path to a language implementation "
+ "location, using any filesystem supported by Apache VFS";

private Main() {
}

private static StyledText error(String[] args) {
StringBuilder invalidArgs = new StringBuilder();
for (String arg : args) {
invalidArgs.append(arg).append(", ");
}
// Remove the appended ", " from the string.
invalidArgs.delete(invalidArgs.length() - 2, invalidArgs.length());
return new StyledText(Color.RED, String.format(ERROR, invalidArgs.toString()));
}

/**
* Instantiates and runs a new {@link ConsoleRepl}.
*
* @param args
* The path to a language implementation location, using any URI supported by Apache
* VFS.
* The path to a language implementation location, using any filesystem supported by
* Apache VFS.
*/
// TODO: make the argument work again.
public static void main(String[] args) {
Injector injector = Guice.createInjector(new ConsoleReplModule());
IDisplay display = injector.getInstance(IDisplay.class);
Expand All @@ -37,6 +49,12 @@ public static void main(String[] args) {
display.displayStyledText(message);

ConsoleRepl repl = injector.getInstance(ConsoleRepl.class);
if (args.length == 1) {
repl.runOnce(":load " + args[0]);
} else if (args.length > 1) {
display.displayStyledText(error(args));
}

repl.run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ public String description() {
@Override
public IResult execute(String... args) {
ConsoleRepl repl = replProvider.get();
return (visitor) -> {
repl.setRunning(false);
};
return (visitor) -> repl.setRunning(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ public void setRunning(boolean running) {
this.running = running;
}

/**
* Evaluate {@code input}, without having to enter the main loop in {@link #run()}. This is
* useful to initialize some state before control is handed to the user.
*
* @param input
* The input to evaluate.
*/
public void runOnce(String input) {
try {
eval(input).accept(display);
} catch (CommandNotFoundException e) {
this.display.displayStyledText(new StyledText(Color.RED, e.getMessage()));
}
}

/**
* Run {@link IRepl#eval(String)} in a loop, for as long as {@code running} is {@code true}.
*
Expand All @@ -65,11 +80,7 @@ public void run() {
String input;
setRunning(true);
while (running && (input = this.iface.getInput()) != null) {
try {
eval(input).accept(display);
} catch (CommandNotFoundException e) {
this.display.displayStyledText(new StyledText(Color.RED, e.getMessage()));
}
runOnce(input);
}

this.iface.history().persistToDisk();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,10 @@ public class TerminalUserInterface implements IDisplay {
* The {@link PrintStream} to write errors to.
* @param hist
* The input history adapter for JLine2.
* @throws IOException
* When an IO error occurs.
*/
@Inject
public TerminalUserInterface(ConsoleReader reader, @Named("out") OutputStream out,
@Named("err") OutputStream err, IInputHistory hist)
throws IOException {
@Named("err") OutputStream err, IInputHistory hist) {
this.reader = reader;
this.hist = hist;
reader.setExpandEvents(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import java.io.File;
import java.io.IOException;
import java.util.Optional;
import java.util.function.Function;

import com.google.inject.Inject;
import com.google.inject.name.Named;

import jline.console.history.History;

/**
* An extension to the adapter for JLine2's History implementation. This adapter implementation
* maintains two versions of JLine2's History classes: one that is initially used in-memory, and
Expand Down Expand Up @@ -49,10 +52,10 @@ public JLine2PersistentInputHistory(@Named("historyPath") String filePath,
* used instead.
*/
@Override
protected jline.console.history.History delegate() {
protected History delegate() {
// orElse does not work on a subtype, but it does if you put flatMap in between.
return delegateFileHist
.flatMap((jline.console.history.History fileHist) -> Optional.of(fileHist))
.flatMap((Function<History, Optional<History>>) Optional::of)
.orElse(super.delegate());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* This package contains implementations (one volatile, one persistent) of
* {@link org.metaborg.spoofax.shell.client.console.IInputHistory}.
* {@link org.metaborg.spoofax.shell.client.IInputHistory}.
*/
package org.metaborg.spoofax.shell.client.console.impl.history;
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.metaborg.spoofax.shell.client.console.impl;

import static org.junit.Assert.fail;
import static org.metaborg.spoofax.shell.client.console.impl.TerminalUserInterfaceTest.C_D;
import static org.metaborg.spoofax.shell.client.console.impl.TerminalUserInterfaceTest.ENTER;
import static org.mockito.Matchers.anyString;
Expand Down Expand Up @@ -91,19 +90,41 @@ private void setUpCtrlD() throws IOException {
createRepl(new UserInputSimulationModule(in, out), new MockModule(invokerMock));
}

/**
* Test {@link ConsoleRepl#runOnce(String)}.
*
* @throws IOException
* Should not happen.
* @throws CommandNotFoundException
* Should not happen.
*/
@Test
public void testRunOnce() throws IOException, CommandNotFoundException {
String fake = ":fakecommand foo";
setUp(fake);
invokerMock = mock(ICommandInvoker.class, RETURNS_MOCKS);

// Create a user input simulated ConsoleRepl with the mock invoker.
createRepl(new UserInputSimulationModule(in, out), new MockModule(invokerMock));

repl.runOnce(fake);
verify(invokerMock, times(1)).execute(fake);
}

/**
* Test whether the REPl exits when Control-D is pressed.
*
* @throws IOException
* Should not happen.
* @throws CommandNotFoundException
* Should not happen.
*/
@Test
public void testCtrlDDoesExit() {
try {
setUpCtrlD();
repl.run();
// Ensure that the command invoker is never called with any command.
verify(invokerMock, never()).execute(anyString());
} catch (IOException | CommandNotFoundException e) {
fail("Should not happen");
}
public void testCtrlDDoesExit() throws CommandNotFoundException, IOException {
setUpCtrlD();
repl.run();
// Ensure that the command invoker is never called with any command.
verify(invokerMock, never()).execute(anyString());
}

private void setUpExit() throws IOException {
Expand All @@ -118,28 +139,29 @@ private void setUpExit() throws IOException {

/**
* Tests the {@link ExitCommand}.
*
* @throws IOException
* Should not happen.
* @throws CommandNotFoundException
* Should not happen.
*/
@Test
public void testExitCommand() {
try {
setUpExit();
public void testExitCommand() throws IOException, CommandNotFoundException {
setUpExit();

// Stub the invoker so that it returns an exit command which we can spy on.
ExitCommand exitCommandMock = spy(new ExitCommand(() -> repl));
when(invokerMock.commandFromName("exit")).thenReturn(exitCommandMock);
// Stub the invoker so that it returns an exit command which we can spy on.
ExitCommand exitCommandMock = spy(new ExitCommand(() -> repl));
when(invokerMock.commandFromName("exit")).thenReturn(exitCommandMock);

repl.run();
repl.run();

// Ensure that the command was given to the invoker just once.
verify(invokerMock, times(1)).execute(":exit");
// Ensure that the command was given to the invoker just once.
verify(invokerMock, times(1)).execute(":exit");

// Ensure that exitCommand was executed once.
verify(exitCommandMock, times(1)).execute();
// Ensure that exitCommand was executed once.
verify(exitCommandMock, times(1)).execute();

// Verify that the Editor was not asked for input after the exit command was executed.
verify(ifaceSpy, times(1)).getInput();
} catch (IOException | CommandNotFoundException e) {
fail("Should not happen");
}
// Verify that the Editor was not asked for input after the exit command was executed.
verify(ifaceSpy, times(1)).getInput();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.io.OutputStream;

import org.junit.Test;
import org.metaborg.spoofax.shell.client.console.impl.TerminalUserInterface;
import org.metaborg.spoofax.shell.output.StyledText;

import com.google.inject.Guice;
Expand All @@ -37,7 +36,6 @@ public class TerminalUserInterfaceTest {
/* >>> */ + "qwerty" + ENTER
/* ... */ + ENTER;
private TerminalUserInterface ui;
private ByteArrayInputStream in;
private ByteArrayOutputStream out;

/**
Expand All @@ -49,7 +47,7 @@ public class TerminalUserInterfaceTest {
* When an IO error occurs upon construction of the {@link ConsoleReader}.
*/
public void setUp(String inputString) throws IOException {
in = new ByteArrayInputStream(inputString.getBytes("UTF-8"));
ByteArrayInputStream in = new ByteArrayInputStream(inputString.getBytes("UTF-8"));
out = new ByteArrayOutputStream();

Injector injector = Guice.createInjector(new UserInputSimulationModule(in, out));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import org.metaborg.core.resource.IResourceService;
import org.metaborg.core.resource.ResourceService;
import org.metaborg.spoofax.core.SpoofaxModule;
import org.metaborg.spoofax.shell.client.IDisplay;
import org.metaborg.spoofax.shell.client.IRepl;
import org.metaborg.spoofax.shell.commands.DefaultCommand;
import org.metaborg.spoofax.shell.commands.HelpCommand;
import org.metaborg.spoofax.shell.commands.IReplCommand;
import org.metaborg.spoofax.shell.commands.LanguageCommand;
Expand Down Expand Up @@ -61,7 +63,8 @@ public abstract class ReplModule extends SpoofaxModule {
protected void bindCommands(MapBinder<String, IReplCommand> commandBinder) {
commandBinder.addBinding("help").to(HelpCommand.class);
commandBinder.addBinding("load").to(LanguageCommand.class);

bind(IReplCommand.class).annotatedWith(Names.named("default_command"))
.to(DefaultCommand.class);
bind(ICommandInvoker.class).to(SpoofaxCommandInvoker.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ default void visitFailure(FailResult errorResult) {
StyledText styled = highlightMessagesInSource(sourceText, messages);

String concat =
messages.stream().map(message -> message.message()).collect(Collectors.joining("\n"));
messages.stream().map(IMessage::message).collect(Collectors.joining("\n"));
visitMessage(styled.append("\n").append(Color.RED, concat));
}

Expand All @@ -64,7 +64,7 @@ default void visitFailure(FailResult errorResult) {
* @return The highlighted {@link StyledText}
*/
default StyledText highlightMessagesInSource(String sourceText, List<IMessage> messages) {
List<ISourceRegion> regions = messages.stream().map(message -> message.region())
List<ISourceRegion> regions = messages.stream().map(IMessage::region)
.filter(Objects::nonNull).collect(Collectors.toList());
StyledText styled = new StyledText();
IStyle style = new Style(Color.RED, null, true, false, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.metaborg.spoofax.shell.commands;

import org.metaborg.spoofax.shell.output.IResult;
import org.metaborg.spoofax.shell.output.StyledText;

/**
* Dummy class returned only when no language is loaded.
*/
public class DefaultCommand implements IReplCommand {
@Override
public String description() {
return "No language is loaded yet, type :help for more information.";
}

@Override
public IResult execute(String... args) {
return (visitor) -> visitor.visitMessage(new StyledText(description()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class HelpCommand implements IReplCommand {
private final ICommandInvoker invoker;

/**
* Instantiates a new HelpCommand.
* Instantiates a new {@link HelpCommand}.
*
* @param invoker
* The {@link ICommandInvoker}.
Expand All @@ -41,7 +41,7 @@ public String description() {
* @return a formatted string
*/
public String formathelp(Map<String, IReplCommand> commands) {
int longestCommand = commands.keySet().stream().mapToInt(a -> a.length()).max().orElse(0);
int longestCommand = commands.keySet().stream().mapToInt(String::length).max().orElse(0);
String format = "%-" + longestCommand + "s %s";

return commands.keySet().stream().flatMap(name -> {
Expand Down
Loading

0 comments on commit 4c8302f

Please sign in to comment.