| Index: lib/dartdoc/classify.dart
|
| diff --git a/lib/dartdoc/classify.dart b/lib/dartdoc/classify.dart
|
| index 933559196cb4de759de73b3a50f9060e86fe2ab2..7090bce8dbf73a48e8dd7e53c2a962db363d562f 100644
|
| --- a/lib/dartdoc/classify.dart
|
| +++ b/lib/dartdoc/classify.dart
|
| @@ -4,7 +4,7 @@
|
|
|
| #library('classify');
|
|
|
| -#import('frog/lang.dart');
|
| +#import('../compiler/implementation/scanner/scannerlib.dart');
|
| #import('markdown.dart', prefix: 'md');
|
|
|
| /**
|
| @@ -33,40 +33,41 @@ class Classification {
|
| static final STRING_INTERPOLATION = 'si';
|
| }
|
|
|
| -String classifySource(SourceFile src) {
|
| +String classifySource(String text) {
|
| var html = new StringBuffer();
|
| - var tokenizer = new Tokenizer(src, /*skipWhitespace:*/false);
|
| + var tokenizer = new StringScanner(text, includeComments: true);
|
|
|
| - var token;
|
| + var whitespaceOffset = 0;
|
| + var token = tokenizer.tokenize();
|
| var inString = false;
|
| - while ((token = tokenizer.next()).kind != TokenKind.END_OF_FILE) {
|
| + while (token.kind != EOF_TOKEN) {
|
| + html.add(text.substring(whitespaceOffset, token.charOffset));
|
| + whitespaceOffset = token.charOffset + token.slowCharCount;
|
|
|
| // Track whether or not we're in a string.
|
| switch (token.kind) {
|
| - case TokenKind.STRING:
|
| - case TokenKind.STRING_PART:
|
| - case TokenKind.INCOMPLETE_STRING:
|
| - case TokenKind.INCOMPLETE_MULTILINE_STRING_DQ:
|
| - case TokenKind.INCOMPLETE_MULTILINE_STRING_SQ:
|
| + case STRING_TOKEN:
|
| + case STRING_INTERPOLATION_TOKEN:
|
| inString = true;
|
| break;
|
| }
|
|
|
| final kind = classify(token);
|
| - final text = md.escapeHtml(token.text);
|
| + final escapedText = md.escapeHtml(token.slowToString());
|
| if (kind != null) {
|
| // Add a secondary class to tokens appearing within a string so that
|
| // we can highlight tokens in an interpolation specially.
|
| var stringClass = inString ? Classification.STRING_INTERPOLATION : '';
|
| - html.add('<span class="$kind $stringClass">$text</span>');
|
| + html.add('<span class="$kind $stringClass">$escapedText</span>');
|
| } else {
|
| - html.add('<span>$text</span>');
|
| + html.add(escapedText);
|
| }
|
|
|
| // Track whether or not we're in a string.
|
| - if (token.kind == TokenKind.STRING) {
|
| + if (token.kind == STRING_TOKEN) {
|
| inString = false;
|
| }
|
| + token = token.next;
|
| }
|
| return html.toString();
|
| }
|
| @@ -93,154 +94,108 @@ bool isLower(String s) => s.toUpperCase() != s;
|
|
|
| String classify(Token token) {
|
| switch (token.kind) {
|
| - case TokenKind.ERROR:
|
| + case UNKNOWN_TOKEN:
|
| return Classification.ERROR;
|
|
|
| - case TokenKind.IDENTIFIER:
|
| + case IDENTIFIER_TOKEN:
|
| // Special case for names that look like types.
|
| - if (_looksLikeType(token.text)
|
| - || token.text == 'num'
|
| - || token.text == 'bool'
|
| - || token.text == 'int'
|
| - || token.text == 'double') {
|
| + final text = token.slowToString();
|
| + if (_looksLikeType(text)
|
| + || text == 'num'
|
| + || text == 'bool'
|
| + || text == 'int'
|
| + || text == 'double') {
|
| return Classification.TYPE_IDENTIFIER;
|
| }
|
| return Classification.IDENTIFIER;
|
|
|
| - // Even though it's a reserved word, let's try coloring it like a type.
|
| - case TokenKind.VOID:
|
| - return Classification.TYPE_IDENTIFIER;
|
| -
|
| - case TokenKind.THIS:
|
| - case TokenKind.SUPER:
|
| - return Classification.SPECIAL_IDENTIFIER;
|
| -
|
| - case TokenKind.STRING:
|
| - case TokenKind.STRING_PART:
|
| - case TokenKind.INCOMPLETE_STRING:
|
| - case TokenKind.INCOMPLETE_MULTILINE_STRING_DQ:
|
| - case TokenKind.INCOMPLETE_MULTILINE_STRING_SQ:
|
| + case STRING_TOKEN:
|
| + case STRING_INTERPOLATION_TOKEN:
|
| return Classification.STRING;
|
|
|
| - case TokenKind.INTEGER:
|
| - case TokenKind.HEX_INTEGER:
|
| - case TokenKind.DOUBLE:
|
| + case INT_TOKEN:
|
| + case HEXADECIMAL_TOKEN:
|
| + case DOUBLE_TOKEN:
|
| return Classification.NUMBER;
|
|
|
| - case TokenKind.COMMENT:
|
| - case TokenKind.INCOMPLETE_COMMENT:
|
| + case COMMENT_TOKEN:
|
| return Classification.COMMENT;
|
|
|
| // => is so awesome it is in a class of its own.
|
| - case TokenKind.ARROW:
|
| + case FUNCTION_TOKEN:
|
| return Classification.ARROW_OPERATOR;
|
|
|
| - case TokenKind.HASHBANG:
|
| - case TokenKind.LPAREN:
|
| - case TokenKind.RPAREN:
|
| - case TokenKind.LBRACK:
|
| - case TokenKind.RBRACK:
|
| - case TokenKind.LBRACE:
|
| - case TokenKind.RBRACE:
|
| - case TokenKind.COLON:
|
| - case TokenKind.SEMICOLON:
|
| - case TokenKind.COMMA:
|
| - case TokenKind.DOT:
|
| - case TokenKind.ELLIPSIS:
|
| + case OPEN_PAREN_TOKEN:
|
| + case CLOSE_PAREN_TOKEN:
|
| + case OPEN_SQUARE_BRACKET_TOKEN:
|
| + case CLOSE_SQUARE_BRACKET_TOKEN:
|
| + case OPEN_CURLY_BRACKET_TOKEN:
|
| + case CLOSE_CURLY_BRACKET_TOKEN:
|
| + case COLON_TOKEN:
|
| + case SEMICOLON_TOKEN:
|
| + case COMMA_TOKEN:
|
| + case PERIOD_TOKEN:
|
| + case PERIOD_PERIOD_TOKEN:
|
| return Classification.PUNCTUATION;
|
|
|
| - case TokenKind.INCR:
|
| - case TokenKind.DECR:
|
| - case TokenKind.BIT_NOT:
|
| - case TokenKind.NOT:
|
| - case TokenKind.ASSIGN:
|
| - case TokenKind.ASSIGN_OR:
|
| - case TokenKind.ASSIGN_XOR:
|
| - case TokenKind.ASSIGN_AND:
|
| - case TokenKind.ASSIGN_SHL:
|
| - case TokenKind.ASSIGN_SAR:
|
| - case TokenKind.ASSIGN_SHR:
|
| - case TokenKind.ASSIGN_ADD:
|
| - case TokenKind.ASSIGN_SUB:
|
| - case TokenKind.ASSIGN_MUL:
|
| - case TokenKind.ASSIGN_DIV:
|
| - case TokenKind.ASSIGN_TRUNCDIV:
|
| - case TokenKind.ASSIGN_MOD:
|
| - case TokenKind.CONDITIONAL:
|
| - case TokenKind.OR:
|
| - case TokenKind.AND:
|
| - case TokenKind.BIT_OR:
|
| - case TokenKind.BIT_XOR:
|
| - case TokenKind.BIT_AND:
|
| - case TokenKind.SHL:
|
| - case TokenKind.SAR:
|
| - case TokenKind.SHR:
|
| - case TokenKind.ADD:
|
| - case TokenKind.SUB:
|
| - case TokenKind.MUL:
|
| - case TokenKind.DIV:
|
| - case TokenKind.TRUNCDIV:
|
| - case TokenKind.MOD:
|
| - case TokenKind.EQ:
|
| - case TokenKind.NE:
|
| - case TokenKind.EQ_STRICT:
|
| - case TokenKind.NE_STRICT:
|
| - case TokenKind.LT:
|
| - case TokenKind.GT:
|
| - case TokenKind.LTE:
|
| - case TokenKind.GTE:
|
| - case TokenKind.INDEX:
|
| - case TokenKind.SETINDEX:
|
| + case PLUS_PLUS_TOKEN:
|
| + case MINUS_MINUS_TOKEN:
|
| + case TILDE_TOKEN:
|
| + case BANG_TOKEN:
|
| + case EQ_TOKEN:
|
| + case BAR_EQ_TOKEN:
|
| + case CARET_EQ_TOKEN:
|
| + case AMPERSAND_EQ_TOKEN:
|
| + case LT_LT_EQ_TOKEN:
|
| + case GT_GT_GT_EQ_TOKEN:
|
| + case GT_GT_EQ_TOKEN:
|
| + case PLUS_EQ_TOKEN:
|
| + case MINUS_EQ_TOKEN:
|
| + case STAR_EQ_TOKEN:
|
| + case SLASH_EQ_TOKEN:
|
| + case TILDE_SLASH_EQ_TOKEN:
|
| + case PERCENT_EQ_TOKEN:
|
| + case QUESTION_TOKEN:
|
| + case BAR_BAR_TOKEN:
|
| + case AMPERSAND_AMPERSAND_TOKEN:
|
| + case BAR_TOKEN:
|
| + case CARET_TOKEN:
|
| + case AMPERSAND_TOKEN:
|
| + case LT_LT_TOKEN:
|
| + case GT_GT_GT_TOKEN:
|
| + case GT_GT_TOKEN:
|
| + case PLUS_TOKEN:
|
| + case MINUS_TOKEN:
|
| + case STAR_TOKEN:
|
| + case SLASH_TOKEN:
|
| + case TILDE_SLASH_TOKEN:
|
| + case PERCENT_TOKEN:
|
| + case EQ_EQ_TOKEN:
|
| + case BANG_EQ_TOKEN:
|
| + case EQ_EQ_EQ_TOKEN:
|
| + case BANG_EQ_EQ_TOKEN:
|
| + case LT_TOKEN:
|
| + case GT_TOKEN:
|
| + case LT_EQ_TOKEN:
|
| + case GT_EQ_TOKEN:
|
| + case INDEX_TOKEN:
|
| + case INDEX_EQ_TOKEN:
|
| return Classification.OPERATOR;
|
|
|
| - // Color this like a keyword
|
| - case TokenKind.HASH:
|
| -
|
| - case TokenKind.ABSTRACT:
|
| - case TokenKind.ASSERT:
|
| - case TokenKind.CLASS:
|
| - case TokenKind.EXTENDS:
|
| - case TokenKind.FACTORY:
|
| - case TokenKind.GET:
|
| - case TokenKind.IMPLEMENTS:
|
| - case TokenKind.IMPORT:
|
| - case TokenKind.INTERFACE:
|
| - case TokenKind.LIBRARY:
|
| - case TokenKind.NATIVE:
|
| - case TokenKind.NEGATE:
|
| - case TokenKind.OPERATOR:
|
| - case TokenKind.SET:
|
| - case TokenKind.SOURCE:
|
| - case TokenKind.STATIC:
|
| - case TokenKind.TYPEDEF:
|
| - case TokenKind.BREAK:
|
| - case TokenKind.CASE:
|
| - case TokenKind.CATCH:
|
| - case TokenKind.CONST:
|
| - case TokenKind.CONTINUE:
|
| - case TokenKind.DEFAULT:
|
| - case TokenKind.DO:
|
| - case TokenKind.ELSE:
|
| - case TokenKind.FALSE:
|
| - case TokenKind.FINALLY:
|
| - case TokenKind.FOR:
|
| - case TokenKind.IF:
|
| - case TokenKind.IN:
|
| - case TokenKind.IS:
|
| - case TokenKind.NEW:
|
| - case TokenKind.NULL:
|
| - case TokenKind.RETURN:
|
| - case TokenKind.SWITCH:
|
| - case TokenKind.THROW:
|
| - case TokenKind.TRUE:
|
| - case TokenKind.TRY:
|
| - case TokenKind.WHILE:
|
| - case TokenKind.VAR:
|
| - case TokenKind.FINAL:
|
| + // Color keyword token. Most are colored as keywords.
|
| + case HASH_TOKEN:
|
| + case KEYWORD_TOKEN:
|
| + if (token.stringValue === 'void') {
|
| + // Color "void" as a type.
|
| + return Classification.TYPE_IDENTIFIER;
|
| + }
|
| + if (token.stringValue === 'this' || token.stringValue === 'super') {
|
| + // Color "this" and "super" as identifiers.
|
| + return Classification.SPECIAL_IDENTIFIER;
|
| + }
|
| return Classification.KEYWORD;
|
|
|
| - case TokenKind.WHITESPACE:
|
| - case TokenKind.END_OF_FILE:
|
| + case EOF_TOKEN:
|
| return Classification.NONE;
|
|
|
| default:
|
|
|