package org.coffeebrew.lang.lexer;
import com.intellij.lexer.FlexAdapter;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* The lexer is tested by comparing modified CoffeeScript lexer tokens
* to the tokens generated by CoffeeScriptFlexLexer.
*
* 1. Place your tests in CoffeeScript under /resources/coffee-script
*
* 2. Start the Ant target 'generate-tokes', which will then pass these example to the CoffeeScript
* compiler and stores the generated lexer token output to /resources/coffee-script
*
* 3. Modify the generated token file to match the plugin token stream and put the CoffeeScript
* file and the token file into /resources/coffee-script/tests
*
* @author Michael Kessler
* @since 0.1.0
*/
class CoffeeScriptLexerExampleTestCase {
private static final String NL = System.getProperty("line.separator");
private static final String FS = System.getProperty("file.separator");
private enum FileType { TOKENS, COFFEE }
/**
* Assert that the CoffeeScript tokens matches the example tokens
*
* @param example The name of the example
*/
protected void assertLexerExample(String example) {
try {
assertThat(getExpectedTokens(example), equalTo(getExampleTokens(example)));
} catch (FileNotFoundException e) {
fail("File not found: " + e.getMessage());
} catch (IOException e) {
fail("Cannot read file: " + e.getMessage());
}
}
/**
* Uses generated tokens from CoffeeScript
*
* @param example The example file name
* @return the lexer tokens
* @throws IOException when the example cannot be read
*/
private static Collection<CoffeeScriptLexerTestToken> getExampleTokens(String example) throws IOException {
ArrayList<CoffeeScriptLexerTestToken> tokens = new ArrayList<CoffeeScriptLexerTestToken>();
StringBuffer content = readFile(example, FileType.TOKENS);
Pattern pattern = Pattern.compile("(\\[[A-Z_]+ .*?\\](?=\\s))", Pattern.MULTILINE);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
CoffeeScriptLexerTestToken token = new CoffeeScriptLexerTestToken(content.substring(matcher.start(), matcher.end()));
tokens.add(token);
}
return tokens;
}
/**
* Uses the plugin to generate the lexer tokens for the given filename
*
* @param example The example file name
* @return the lexer tokens
* @throws IOException when the example cannot be read
*/
private static Collection<CoffeeScriptLexerTestToken> getExpectedTokens(String example) throws IOException {
final FlexAdapter lexer = new CoffeeScriptFlexLexer();
lexer.start(readFile(example, FileType.COFFEE));
ArrayList<CoffeeScriptLexerTestToken> tokens = new ArrayList<CoffeeScriptLexerTestToken>();
while (lexer.getCurrentPosition().getOffset() < lexer.getBufferEnd()) {
CoffeeScriptLexerTestToken token = new CoffeeScriptLexerTestToken(lexer.getTokenType(), lexer.getTokenSequence());
tokens.add(token);
lexer.advance();
}
return tokens;
}
/**
* Reads the given file and returns its content as StringBuffer
*
* @param example The example name
* @param type The example type
* @return the content of the file
* @throws IOException when the example cannot be read
*/
private static StringBuffer readFile(String example, FileType type) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(getExampleFilePath(example, type)));
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line).append(NL);
}
return buffer;
}
/**
* Returns the path and filename to the example file for the given type
*
* @param example The example name
* @param type The example type
* @return the path and filename
*/
private static String getExampleFilePath(String example, FileType type) {
String filename;
String basePath = getProjectHome() + FS + "resources" + FS + "coffee-script" + FS + "tests" + FS;
if (type == FileType.COFFEE) {
filename = basePath + example + ".coffee";
} else {
filename = basePath + example + ".tokens";
}
return filename;
}
/**
*
* @return the project home directory
*/
private static String getProjectHome() {
Properties props = System.getProperties();
return props.getProperty("user.dir");
}
}