Apply pedantic

This commit is contained in:
Tobe O 2019-07-29 18:12:52 -04:00
parent e7df87d0c2
commit 3d5ac69ab2
26 changed files with 222 additions and 213 deletions

View file

@ -33,9 +33,9 @@ void myFunction() {
</html>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael', asDSX: false);
var scope = new SymbolTable(values: {
var scope = SymbolTable(values: {
'profile': {
'avatar': 'thosakwe.png',
}

View file

@ -6,7 +6,7 @@ import 'package:symbol_table/symbol_table.dart';
main() {
while (true) {
var buf = new StringBuffer();
var buf = StringBuffer();
int ch;
print('Enter lines of Jael text, terminated by CTRL^D.');
print('All environment variables are injected into the template scope.');
@ -24,11 +24,11 @@ main() {
if (document == null) {
stderr.writeln('Could not parse the given text.');
} else {
var output = new CodeBuffer();
var output = CodeBuffer();
const jael.Renderer().render(
document,
output,
new SymbolTable(values: Platform.environment),
SymbolTable(values: Platform.environment),
strictResolution: false,
);
print('GENERATED HTML:\n$output');

View file

@ -37,7 +37,7 @@ class BinaryExpression extends Expression {
case TokenType.elvis:
return l ?? r;
default:
throw new UnsupportedError(
throw UnsupportedError(
'Unsupported binary operator: "${operator?.span?.text ?? "<null>"}".');
}
}

View file

@ -28,7 +28,7 @@ class Call extends Expression {
Map<Symbol, dynamic> computeNamed(SymbolTable scope) {
return namedArguments.fold<Map<Symbol, dynamic>>({}, (out, a) {
return out..[new Symbol(a.name.name)] = a.value.compute(scope);
return out..[Symbol(a.name.name)] = a.value.compute(scope);
});
}

View file

@ -46,8 +46,9 @@ class Doctype extends AstNode {
@override
FileSpan get span {
if (public == null)
if (public == null) {
return lt.span.expand(doctype.span).expand(html.span).expand(gt.span);
}
return lt.span
.expand(doctype.span)
.expand(html.span)

View file

@ -16,7 +16,7 @@ class TextNode extends ElementChild {
}
abstract class Element extends ElementChild {
static const List<String> selfClosing = const [
static const List<String> selfClosing = [
'include',
'base',
'basefont',

View file

@ -21,8 +21,7 @@ class Identifier extends Expression {
var symbol = scope.resolve(name);
if (symbol == null) {
if (scope.resolve('!strict!')?.value == false) return null;
throw new ArgumentError(
'The name "$name" does not exist in this scope.');
throw ArgumentError('The name "$name" does not exist in this scope.');
}
return scope.resolve(name).value;
}
@ -43,6 +42,6 @@ class SyntheticIdentifier extends Identifier {
@override
FileSpan get span {
if (id != null) return id.span;
throw new UnsupportedError('Cannot get the span of a SyntheticIdentifier.');
throw UnsupportedError('Cannot get the span of a SyntheticIdentifier.');
}
}

View file

@ -16,7 +16,7 @@ class MemberExpression extends Expression {
compute(SymbolTable scope) {
var target = expression.compute(scope);
if (op.span.text == '?.' && target == null) return null;
return reflect(target).getField(new Symbol(name.name)).reflectee;
return reflect(target).getField(Symbol(name.name)).reflectee;
}
@override

View file

@ -21,11 +21,12 @@ class NewExpression extends Expression {
var named = call.computeNamed(scope);
var name = '';
if (call.target is MemberExpression)
if (call.target is MemberExpression) {
name = (call.target as MemberExpression).name.name;
}
return reflectClass(targetType as Type)
.newInstance(new Symbol(name), positional, named)
.newInstance(Symbol(name), positional, named)
.reflectee;
}
}

View file

@ -14,7 +14,7 @@ class StringLiteral extends Literal {
static String parseValue(Token string) {
var text = string.span.text.substring(1, string.span.text.length - 1);
var codeUnits = text.codeUnits;
var buf = new StringBuffer();
var buf = StringBuffer();
for (int i = 0; i < codeUnits.length; i++) {
var ch = codeUnits[i];
@ -25,9 +25,9 @@ class StringLiteral extends Literal {
c2 = codeUnits[++i],
c3 = codeUnits[++i],
c4 = codeUnits[++i];
var hexString = new String.fromCharCodes([c1, c2, c3, c4]);
var hexString = String.fromCharCodes([c1, c2, c3, c4]);
var hexNumber = int.parse(hexString, radix: 16);
buf.write(new String.fromCharCode(hexNumber));
buf.write(String.fromCharCode(hexNumber));
continue;
}
@ -53,9 +53,10 @@ class StringLiteral extends Literal {
default:
buf.writeCharCode(next);
}
} else
throw new JaelError(JaelErrorSeverity.error,
} else {
throw JaelError(JaelErrorSeverity.error,
'Unexpected "\\" in string literal.', string.span);
}
} else {
buf.writeCharCode(ch);
}

View file

@ -5,12 +5,12 @@ class JaelFormatter {
final num tabSize;
final bool insertSpaces;
final int maxLineLength;
var _buffer = new StringBuffer();
var _buffer = StringBuffer();
int _level = 0;
String _spaces;
static String _spaceString(int tabSize) {
var b = new StringBuffer();
var b = StringBuffer();
for (int i = 0; i < tabSize; i++) {
b.write(' ');
}
@ -30,7 +30,9 @@ class JaelFormatter {
}
void _applySpacing() {
for (int i = 0; i < _level; i++) _buffer.write(_spaces);
for (int i = 0; i < _level; i++) {
_buffer.write(_spaces);
}
}
int get _spaceLength {
@ -62,9 +64,9 @@ class JaelFormatter {
int _formatChild(ElementChild child, int lineLength,
{bool isFirst = false, bool isLast = false}) {
if (child == null)
if (child == null) {
return lineLength;
else if (child is Element) return _formatElement(child, lineLength);
} else if (child is Element) return _formatElement(child, lineLength);
String s;
if (child is Interpolation) {
var b = StringBuffer('{{');

View file

@ -7,21 +7,21 @@ import 'text/scanner.dart';
/// Parses a Jael document.
Document parseDocument(String text,
{sourceUrl, bool asDSX: false, void onError(JaelError error)}) {
{sourceUrl, bool asDSX = false, void onError(JaelError error)}) {
var scanner = scan(text, sourceUrl: sourceUrl, asDSX: asDSX);
//scanner.tokens.forEach(print);
if (scanner.errors.isNotEmpty && onError != null)
if (scanner.errors.isNotEmpty && onError != null) {
scanner.errors.forEach(onError);
else if (scanner.errors.isNotEmpty) throw scanner.errors.first;
} else if (scanner.errors.isNotEmpty) throw scanner.errors.first;
var parser = new Parser(scanner, asDSX: asDSX);
var parser = Parser(scanner, asDSX: asDSX);
var doc = parser.parseDocument();
if (parser.errors.isNotEmpty && onError != null)
if (parser.errors.isNotEmpty && onError != null) {
parser.errors.forEach(onError);
else if (parser.errors.isNotEmpty) throw parser.errors.first;
} else if (parser.errors.isNotEmpty) throw parser.errors.first;
return doc;
}
@ -80,7 +80,7 @@ class Renderer {
/// If [strictResolution] is `false` (default: `true`), then undefined identifiers will return `null`
/// instead of throwing.
void render(Document document, CodeBuffer buffer, SymbolTable scope,
{bool strictResolution: true}) {
{bool strictResolution = true}) {
scope.create('!strict!', value: strictResolution != false);
if (document.doctype != null) buffer.writeln(document.doctype.span.text);
@ -126,17 +126,18 @@ class Renderer {
buffer.write(' ${attribute.name}');
if (value == true)
if (value == true) {
continue;
else
} else {
buffer.write('="');
}
String msg;
if (value is Iterable) {
msg = value.join(' ');
} else if (value is Map) {
msg = value.keys.fold<StringBuffer>(new StringBuffer(), (buf, k) {
msg = value.keys.fold<StringBuffer>(StringBuffer(), (buf, k) {
var v = value[k];
if (v == null) return buf;
return buf..write('$k: $v;');
@ -150,10 +151,11 @@ class Renderer {
}
if (element is SelfClosingElement) {
if (html5)
if (html5) {
buffer.writeln('>');
else
} else {
buffer.writeln('/>');
}
} else {
buffer.writeln('>');
buffer.indent();
@ -185,11 +187,11 @@ class Renderer {
(a) => a.name != 'for-each' && a.name != 'as' && a.name != 'index-as');
Element strippedElement;
if (element is SelfClosingElement)
strippedElement = new SelfClosingElement(element.lt, element.tagName,
if (element is SelfClosingElement) {
strippedElement = SelfClosingElement(element.lt, element.tagName,
otherAttributes, element.slash, element.gt);
else if (element is RegularElement)
strippedElement = new RegularElement(
} else if (element is RegularElement) {
strippedElement = RegularElement(
element.lt,
element.tagName,
otherAttributes,
@ -199,6 +201,7 @@ class Renderer {
element.slash,
element.tagName2,
element.gt2);
}
int i = 0;
for (var item in attribute.value.compute(scope)) {
@ -224,11 +227,11 @@ class Renderer {
var otherAttributes = element.attributes.where((a) => a.name != 'if');
Element strippedElement;
if (element is SelfClosingElement)
strippedElement = new SelfClosingElement(element.lt, element.tagName,
if (element is SelfClosingElement) {
strippedElement = SelfClosingElement(element.lt, element.tagName,
otherAttributes, element.slash, element.gt);
else if (element is RegularElement)
strippedElement = new RegularElement(
} else if (element is RegularElement) {
strippedElement = RegularElement(
element.lt,
element.tagName,
otherAttributes,
@ -238,6 +241,7 @@ class Renderer {
element.slash,
element.tagName2,
element.gt2);
}
renderElement(strippedElement, buffer, scope, html5);
}
@ -298,21 +302,23 @@ class Renderer {
void renderElementChild(Element parent, ElementChild child, CodeBuffer buffer,
SymbolTable scope, bool html5, int index, int total) {
if (child is Text && parent?.tagName?.name != 'textarea') {
if (index == 0)
if (index == 0) {
buffer.write(child.span.text.trimLeft());
else if (index == total - 1)
} else if (index == total - 1) {
buffer.write(child.span.text.trimRight());
else
} else {
buffer.write(child.span.text);
}
} else if (child is Interpolation) {
var value = child.expression.compute(scope);
if (value != null) {
if (child.isRaw)
if (child.isRaw) {
buffer.write(value);
else
} else {
buffer.write(htmlEscape.convert(value.toString()));
}
}
} else if (child is Element) {
if (buffer?.lastLine?.text?.isNotEmpty == true) buffer.writeln();
renderElement(child, buffer, scope, html5);
@ -324,14 +330,14 @@ class Renderer {
void registerCustomElement(
Element element, CodeBuffer buffer, SymbolTable scope, bool html5) {
if (element is! RegularElement) {
throw new JaelError(JaelErrorSeverity.error,
throw JaelError(JaelErrorSeverity.error,
"Custom elements cannot be self-closing.", element.span);
}
var name = element.getAttribute('name')?.value?.compute(scope)?.toString();
if (name == null) {
throw new JaelError(
throw JaelError(
JaelErrorSeverity.error,
"Attribute 'name' is required when registering a custom element.",
element.tagName.span);
@ -341,7 +347,7 @@ class Renderer {
var p = scope.isRoot ? scope : scope.parent;
p.create(customElementName(name), value: element, constant: true);
} on StateError {
throw new JaelError(
throw JaelError(
JaelErrorSeverity.error,
"Cannot re-define element '$name' in this scope.",
element.getAttribute('name').span);
@ -371,16 +377,16 @@ class Renderer {
} else {
var tagName = renderAs?.toString() ?? 'div';
var syntheticElement = new RegularElement(
var syntheticElement = RegularElement(
template.lt,
new SyntheticIdentifier(tagName),
SyntheticIdentifier(tagName),
element.attributes
.where((a) => a.name != 'as' && !a.name.startsWith('@')),
template.gt,
template.children,
template.lt2,
template.slash,
new SyntheticIdentifier(tagName),
SyntheticIdentifier(tagName),
template.gt2);
renderElement(syntheticElement, buffer, scope, html5);

View file

@ -1,24 +1,24 @@
part of jael.src.text.parselet;
const Map<TokenType, InfixParselet> infixParselets = const {
TokenType.lParen: const CallParselet(),
TokenType.elvis_dot: const MemberParselet(),
TokenType.dot: const MemberParselet(),
TokenType.lBracket: const IndexerParselet(),
TokenType.asterisk: const BinaryParselet(14),
TokenType.slash: const BinaryParselet(14),
TokenType.percent: const BinaryParselet(14),
TokenType.plus: const BinaryParselet(13),
TokenType.minus: const BinaryParselet(13),
TokenType.lt: const BinaryParselet(11),
TokenType.lte: const BinaryParselet(11),
TokenType.gt: const BinaryParselet(11),
TokenType.gte: const BinaryParselet(11),
TokenType.equ: const BinaryParselet(10),
TokenType.nequ: const BinaryParselet(10),
TokenType.question: const ConditionalParselet(),
TokenType.equals: const BinaryParselet(3),
TokenType.elvis: const BinaryParselet(3),
const Map<TokenType, InfixParselet> infixParselets = {
TokenType.lParen: CallParselet(),
TokenType.elvis_dot: MemberParselet(),
TokenType.dot: MemberParselet(),
TokenType.lBracket: IndexerParselet(),
TokenType.asterisk: BinaryParselet(14),
TokenType.slash: BinaryParselet(14),
TokenType.percent: BinaryParselet(14),
TokenType.plus: BinaryParselet(13),
TokenType.minus: BinaryParselet(13),
TokenType.lt: BinaryParselet(11),
TokenType.lte: BinaryParselet(11),
TokenType.gt: BinaryParselet(11),
TokenType.gte: BinaryParselet(11),
TokenType.equ: BinaryParselet(10),
TokenType.nequ: BinaryParselet(10),
TokenType.question: ConditionalParselet(),
TokenType.equals: BinaryParselet(3),
TokenType.elvis: BinaryParselet(3),
};
class ConditionalParselet implements InfixParselet {
@ -32,13 +32,13 @@ class ConditionalParselet implements InfixParselet {
var ifTrue = parser.parseExpression(0);
if (ifTrue == null) {
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression in conditional expression.', token.span));
return null;
}
if (!parser.next(TokenType.colon)) {
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Missing ":" in conditional expression.', ifTrue.span));
return null;
}
@ -47,12 +47,12 @@ class ConditionalParselet implements InfixParselet {
var ifFalse = parser.parseExpression(0);
if (ifFalse == null) {
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression in conditional expression.', colon.span));
return null;
}
return new Conditional(left, token, ifTrue, colon, ifFalse);
return Conditional(left, token, ifTrue, colon, ifFalse);
}
}
@ -66,15 +66,16 @@ class BinaryParselet implements InfixParselet {
var right = parser.parseExpression(precedence);
if (right == null) {
if (token.type != TokenType.gt)
parser.errors.add(new JaelError(
if (token.type != TokenType.gt) {
parser.errors.add(JaelError(
JaelErrorSeverity.error,
'Missing expression after operator "${token.span.text}", following expression ${left.span.text}.',
token.span));
}
return null;
}
return new BinaryExpression(left, token, right);
return BinaryExpression(left, token, right);
}
}
@ -109,12 +110,12 @@ class CallParselet implements InfixParselet {
if (!parser.next(TokenType.rParen)) {
var lastSpan = arguments.isEmpty ? null : arguments.last.span;
lastSpan ??= token.span;
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Missing ")" after argument list.', lastSpan));
return null;
}
return new Call(left, token, parser.current, arguments, namedArguments);
return Call(left, token, parser.current, arguments, namedArguments);
}
}
@ -129,18 +130,18 @@ class IndexerParselet implements InfixParselet {
var indexer = parser.parseExpression(0);
if (indexer == null) {
parser.errors.add(new JaelError(
parser.errors.add(JaelError(
JaelErrorSeverity.error, 'Missing expression after "[".', left.span));
return null;
}
if (!parser.next(TokenType.rBracket)) {
parser.errors.add(
new JaelError(JaelErrorSeverity.error, 'Missing "]".', indexer.span));
JaelError(JaelErrorSeverity.error, 'Missing "]".', indexer.span));
return null;
}
return new IndexerExpression(left, token, indexer, parser.current);
return IndexerExpression(left, token, indexer, parser.current);
}
}
@ -155,11 +156,11 @@ class MemberParselet implements InfixParselet {
var name = parser.parseIdentifier();
if (name == null) {
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Expected the name of a property following "."', token.span));
return null;
}
return new MemberExpression(left, token, name);
return MemberExpression(left, token, name);
}
}

View file

@ -1,15 +1,15 @@
part of jael.src.text.parselet;
const Map<TokenType, PrefixParselet> prefixParselets = const {
TokenType.exclamation: const NotParselet(),
TokenType.$new: const NewParselet(),
TokenType.number: const NumberParselet(),
TokenType.hex: const HexParselet(),
TokenType.string: const StringParselet(),
TokenType.lCurly: const MapParselet(),
TokenType.lBracket: const ArrayParselet(),
TokenType.id: const IdentifierParselet(),
TokenType.lParen: const ParenthesisParselet(),
const Map<TokenType, PrefixParselet> prefixParselets = {
TokenType.exclamation: NotParselet(),
TokenType.$new: NewParselet(),
TokenType.number: NumberParselet(),
TokenType.hex: HexParselet(),
TokenType.string: StringParselet(),
TokenType.lCurly: MapParselet(),
TokenType.lBracket: ArrayParselet(),
TokenType.id: IdentifierParselet(),
TokenType.lParen: ParenthesisParselet(),
};
class NotParselet implements PrefixParselet {
@ -20,11 +20,11 @@ class NotParselet implements PrefixParselet {
var expression = parser.parseExpression(0);
if (expression == null) {
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression after "!" in negation expression.', token.span));
}
return new Negation(token, expression);
return Negation(token, expression);
}
}
@ -36,15 +36,15 @@ class NewParselet implements PrefixParselet {
var call = parser.parseExpression(0);
if (call == null) {
parser.errors.add(new JaelError(
parser.errors.add(JaelError(
JaelErrorSeverity.error,
'"new" must precede a call expression. Nothing was found.',
call.span));
return null;
} else if (call is Call) {
return new NewExpression(token, call);
return NewExpression(token, call);
} else {
parser.errors.add(new JaelError(
parser.errors.add(JaelError(
JaelErrorSeverity.error,
'"new" must precede a call expression, not a(n) ${call.runtimeType}.',
call.span));
@ -57,14 +57,14 @@ class NumberParselet implements PrefixParselet {
const NumberParselet();
@override
Expression parse(Parser parser, Token token) => new NumberLiteral(token);
Expression parse(Parser parser, Token token) => NumberLiteral(token);
}
class HexParselet implements PrefixParselet {
const HexParselet();
@override
Expression parse(Parser parser, Token token) => new HexLiteral(token);
Expression parse(Parser parser, Token token) => HexLiteral(token);
}
class StringParselet implements PrefixParselet {
@ -72,7 +72,7 @@ class StringParselet implements PrefixParselet {
@override
Expression parse(Parser parser, Token token) =>
new StringLiteral(token, StringLiteral.parseValue(token));
StringLiteral(token, StringLiteral.parseValue(token));
}
class ArrayParselet implements PrefixParselet {
@ -93,12 +93,12 @@ class ArrayParselet implements PrefixParselet {
if (!parser.next(TokenType.rBracket)) {
var lastSpan = items.isEmpty ? null : items.last.span;
lastSpan ??= token.span;
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Missing "]" to terminate array literal.', lastSpan));
return null;
}
return new Array(token, parser.current, items);
return Array(token, parser.current, items);
}
}
@ -119,12 +119,12 @@ class MapParselet implements PrefixParselet {
if (!parser.next(TokenType.rCurly)) {
var lastSpan = pairs.isEmpty ? token.span : pairs.last.span;
parser.errors.add(new JaelError(
parser.errors.add(JaelError(
JaelErrorSeverity.error, 'Missing "}" in map literal.', lastSpan));
return null;
}
return new MapLiteral(token, pairs, parser.current);
return MapLiteral(token, pairs, parser.current);
}
}
@ -132,7 +132,7 @@ class IdentifierParselet implements PrefixParselet {
const IdentifierParselet();
@override
Expression parse(Parser parser, Token token) => new Identifier(token);
Expression parse(Parser parser, Token token) => Identifier(token);
}
class ParenthesisParselet implements PrefixParselet {
@ -143,14 +143,14 @@ class ParenthesisParselet implements PrefixParselet {
var expression = parser.parseExpression(0);
if (expression == null) {
parser.errors.add(new JaelError(JaelErrorSeverity.error,
parser.errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression after "(".', token.span));
return null;
}
if (!parser.next(TokenType.rParen)) {
parser.errors.add(new JaelError(
JaelErrorSeverity.error, 'Missing ")".', expression.span));
parser.errors.add(
JaelError(JaelErrorSeverity.error, 'Missing ")".', expression.span));
return null;
}

View file

@ -10,7 +10,7 @@ class Parser {
Token _current;
int _index = -1;
Parser(this.scanner, {this.asDSX: false});
Parser(this.scanner, {this.asDSX = false});
Token get current => _current;
@ -52,18 +52,18 @@ class Parser {
if (doctype == null) {
var root = parseElement();
if (root == null) return null;
return new Document(null, root);
return Document(null, root);
}
var root = parseElement();
if (root == null) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing root element after !DOCTYPE declaration.', doctype.span));
return null;
}
return new Document(doctype, root);
return Document(doctype, root);
}
StringLiteral implicitString() {
@ -88,7 +88,7 @@ class Parser {
}
var doctype = _current, html = parseIdentifier();
if (html?.span?.text?.toLowerCase() != 'html') {
errors.add(new JaelError(
errors.add(JaelError(
JaelErrorSeverity.error,
'Expected "html" in doctype declaration.',
html?.span ?? doctype.span));
@ -98,16 +98,16 @@ class Parser {
var public = parseIdentifier();
if (public == null) {
if (!next(TokenType.gt)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Expected ">" in doctype declaration.', html.span));
return null;
}
return new Doctype(lt, doctype, html, null, null, null, _current);
return Doctype(lt, doctype, html, null, null, null, _current);
}
if (public?.span?.text?.toLowerCase() != 'public') {
errors.add(new JaelError(
errors.add(JaelError(
JaelErrorSeverity.error,
'Expected "public" in doctype declaration.',
public?.span ?? html.span));
@ -117,7 +117,7 @@ class Parser {
var stringParser = prefixParselets[TokenType.string];
if (!next(TokenType.string)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Expected string in doctype declaration.', public.span));
return null;
}
@ -125,7 +125,7 @@ class Parser {
var name = stringParser.parse(this, _current) as StringLiteral;
if (!next(TokenType.string)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Expected string in doctype declaration.', name.span));
return null;
}
@ -133,12 +133,12 @@ class Parser {
var url = stringParser.parse(this, _current) as StringLiteral;
if (!next(TokenType.gt)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Expected ">" in doctype declaration.', url.span));
return null;
}
return new Doctype(lt, doctype, html, public, name, url, _current);
return Doctype(lt, doctype, html, public, name, url, _current);
}
ElementChild parseElementChild() =>
@ -148,9 +148,9 @@ class Parser {
parseElement();
HtmlComment parseHtmlComment() =>
next(TokenType.htmlComment) ? new HtmlComment(_current) : null;
next(TokenType.htmlComment) ? HtmlComment(_current) : null;
Text parseText() => next(TokenType.text) ? new Text(_current) : null;
Text parseText() => next(TokenType.text) ? Text(_current) : null;
Interpolation parseInterpolation() {
if (!next(asDSX ? TokenType.lCurly : TokenType.lDoubleCurly)) return null;
@ -159,19 +159,19 @@ class Parser {
var expression = parseExpression(0);
if (expression == null) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression in interpolation.', doubleCurlyL.span));
return null;
}
if (!next(asDSX ? TokenType.rCurly : TokenType.rDoubleCurly)) {
var expected = asDSX ? '}' : '}}';
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing closing "$expected" in interpolation.', expression.span));
return null;
}
return new Interpolation(doubleCurlyL, expression, _current);
return Interpolation(doubleCurlyL, expression, _current);
}
Element parseElement() {
@ -188,7 +188,7 @@ class Parser {
if (tagName == null) {
errors.add(
new JaelError(JaelErrorSeverity.error, 'Missing tag name.', lt.span));
JaelError(JaelErrorSeverity.error, 'Missing tag name.', lt.span));
return null;
}
@ -205,16 +205,16 @@ class Parser {
var slash = _current;
if (!next(TokenType.gt)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing ">" in self-closing "${tagName.name}" tag.', slash.span));
return null;
}
return new SelfClosingElement(lt, tagName, attributes, slash, _current);
return SelfClosingElement(lt, tagName, attributes, slash, _current);
}
if (!next(TokenType.gt)) {
errors.add(new JaelError(
errors.add(JaelError(
JaelErrorSeverity.error,
'Missing ">" in "${tagName.name}" tag.',
attributes.isEmpty ? tagName.span : attributes.last.span));
@ -225,7 +225,7 @@ class Parser {
// Implicit self-closing
if (Element.selfClosing.contains(tagName.name)) {
return new SelfClosingElement(lt, tagName, attributes, null, gt);
return SelfClosingElement(lt, tagName, attributes, null, gt);
}
List<ElementChild> children = [];
@ -239,7 +239,7 @@ class Parser {
// Parse closing tag
if (!next(TokenType.lt)) {
errors.add(new JaelError(
errors.add(JaelError(
JaelErrorSeverity.error,
'Missing closing tag for "${tagName.name}" tag.',
children.isEmpty ? tagName.span : children.last.span));
@ -249,7 +249,7 @@ class Parser {
var lt2 = _current;
if (!next(TokenType.slash)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing "/" in "${tagName.name}" closing tag.', lt2.span));
return null;
}
@ -257,7 +257,7 @@ class Parser {
var slash = _current, tagName2 = parseIdentifier();
if (tagName2 == null) {
errors.add(new JaelError(
errors.add(JaelError(
JaelErrorSeverity.error,
'Missing "${tagName.name}" in "${tagName.name}" closing tag.',
slash.span));
@ -265,7 +265,7 @@ class Parser {
}
if (tagName2.name != tagName.name) {
errors.add(new JaelError(
errors.add(JaelError(
JaelErrorSeverity.error,
'Mismatched closing tags. Expected "${tagName.span.text}"; got "${tagName2.name}" instead.',
lt2.span));
@ -273,12 +273,12 @@ class Parser {
}
if (!next(TokenType.gt)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing ">" in "${tagName.name}" closing tag.', tagName2.span));
return null;
}
return new RegularElement(
return RegularElement(
lt, tagName, attributes, gt, children, lt2, slash, tagName2, _current);
}
@ -289,7 +289,7 @@ class Parser {
if ((id = parseIdentifier()) != null) {
// Nothing
} else if (next(TokenType.string)) {
string = new StringLiteral(_current, StringLiteral.parseValue(_current));
string = StringLiteral(_current, StringLiteral.parseValue(_current));
} else {
return null;
}
@ -301,35 +301,34 @@ class Parser {
} else if (!asDSX && next(TokenType.nequ)) {
nequ = _current;
} else {
return new Attribute(id, string, null, null, null);
return Attribute(id, string, null, null, null);
}
if (!asDSX) {
var value = parseExpression(0);
if (value == null) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression in attribute.', equals?.span ?? nequ.span));
return null;
}
return new Attribute(id, string, equals, nequ, value);
return Attribute(id, string, equals, nequ, value);
} else {
// Find either a string, or an interpolation.
var value = implicitString();
if (value != null) {
return new Attribute(id, string, equals, nequ, value);
return Attribute(id, string, equals, nequ, value);
}
var interpolation = parseInterpolation();
if (interpolation != null) {
return new Attribute(
id, string, equals, nequ, interpolation.expression);
return Attribute(id, string, equals, nequ, interpolation.expression);
}
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression in attribute.', equals?.span ?? nequ.span));
return null;
}
@ -374,23 +373,23 @@ class Parser {
}
Identifier parseIdentifier() =>
next(TokenType.id) ? new Identifier(_current) : null;
next(TokenType.id) ? Identifier(_current) : null;
KeyValuePair parseKeyValuePair() {
var key = parseExpression(0);
if (key == null) return null;
if (!next(TokenType.colon)) return new KeyValuePair(key, null, null);
if (!next(TokenType.colon)) return KeyValuePair(key, null, null);
var colon = _current, value = parseExpression(0);
if (value == null) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression in key-value pair.', colon.span));
return null;
}
return new KeyValuePair(key, colon, value);
return KeyValuePair(key, colon, value);
}
NamedArgument parseNamedArgument() {
@ -398,7 +397,7 @@ class Parser {
if (name == null) return null;
if (!next(TokenType.colon)) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing ":" in named argument.', name.span));
return null;
}
@ -406,11 +405,11 @@ class Parser {
var colon = _current, value = parseExpression(0);
if (value == null) {
errors.add(new JaelError(JaelErrorSeverity.error,
errors.add(JaelError(JaelErrorSeverity.error,
'Missing expression in named argument.', colon.span));
return null;
}
return new NamedArgument(name, colon, value);
return NamedArgument(name, colon, value);
}
}

View file

@ -3,17 +3,17 @@ import 'package:charcode/ascii.dart';
import 'package:string_scanner/string_scanner.dart';
import '../ast/ast.dart';
final RegExp _whitespace = new RegExp(r'[ \n\r\t]+');
final RegExp _whitespace = RegExp(r'[ \n\r\t]+');
final RegExp _id =
new RegExp(r'@?(([A-Za-z][A-Za-z0-9_]*-)*([A-Za-z][A-Za-z0-9_]*))');
final RegExp _string1 = new RegExp(
RegExp(r'@?(([A-Za-z][A-Za-z0-9_]*-)*([A-Za-z][A-Za-z0-9_]*))');
final RegExp _string1 = RegExp(
r"'((\\(['\\/bfnrt]|(u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))|([^'\\]))*'");
final RegExp _string2 = new RegExp(
final RegExp _string2 = RegExp(
r'"((\\(["\\/bfnrt]|(u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))|([^"\\]))*"');
Scanner scan(String text, {sourceUrl, bool asDSX: false}) =>
new _Scanner(text, sourceUrl)..scan(asDSX: asDSX);
Scanner scan(String text, {sourceUrl, bool asDSX = false}) =>
_Scanner(text, sourceUrl)..scan(asDSX: asDSX);
abstract class Scanner {
List<JaelError> get errors;
@ -21,7 +21,7 @@ abstract class Scanner {
List<Token> get tokens;
}
final RegExp _htmlComment = new RegExp(r'<!--[^$]*-->');
final RegExp _htmlComment = RegExp(r'<!--[^$]*-->');
final Map<Pattern, TokenType> _expressionPatterns = {
//final Map<Pattern, TokenType> _htmlPatterns = {
@ -74,8 +74,8 @@ final Map<Pattern, TokenType> _expressionPatterns = {
'==': TokenType.equ,
'!=': TokenType.nequ,
'=': TokenType.equals,
new RegExp(r'-?[0-9]+(\.[0-9]+)?([Ee][0-9]+)?'): TokenType.number,
new RegExp(r'0x[A-Fa-f0-9]+'): TokenType.hex,
RegExp(r'-?[0-9]+(\.[0-9]+)?([Ee][0-9]+)?'): TokenType.number,
RegExp(r'0x[A-Fa-f0-9]+'): TokenType.hex,
_string1: TokenType.string,
_string2: TokenType.string,
_id: TokenType.id,
@ -85,15 +85,15 @@ class _Scanner implements Scanner {
final List<JaelError> errors = [];
final List<Token> tokens = [];
_ScannerState state = _ScannerState.html;
final Queue<String> openTags = new Queue();
final Queue<String> openTags = Queue();
SpanScanner _scanner;
_Scanner(String text, sourceUrl) {
_scanner = new SpanScanner(text, sourceUrl: sourceUrl);
_scanner = SpanScanner(text, sourceUrl: sourceUrl);
}
void scan({bool asDSX: false}) {
void scan({bool asDSX = false}) {
while (!_scanner.isDone) {
if (state == _ScannerState.html) {
scanHtml(asDSX);
@ -164,14 +164,15 @@ class _Scanner implements Scanner {
var span = _scanner.spanFrom(start, end);
if (span.text.isNotEmpty)
tokens.add(new Token(TokenType.text, span, null));
if (span.text.isNotEmpty) {
tokens.add(Token(TokenType.text, span, null));
}
}
}
}
void scanHtml(bool asDSX) {
var brackets = new Queue<Token>();
var brackets = Queue<Token>();
do {
// Only continue if we find a left bracket
@ -184,9 +185,9 @@ class _Scanner implements Scanner {
_scanner.scan(_whitespace);
_expressionPatterns.forEach((pattern, type) {
if (_scanner.matches(pattern))
potential
.add(new Token(type, _scanner.lastSpan, _scanner.lastMatch));
if (_scanner.matches(pattern)) {
potential.add(Token(type, _scanner.lastSpan, _scanner.lastMatch));
}
});
potential.sort((a, b) => b.span.length.compareTo(a.span.length));

View file

@ -107,7 +107,7 @@ void main() {
String render(String template, [Map<String, dynamic> values]) {
var doc = jael.parseDocument(template, onError: (e) => throw e);
var buffer = new CodeBuffer();
const jael.Renderer().render(doc, buffer, new SymbolTable(values: values));
var buffer = CodeBuffer();
const jael.Renderer().render(doc, buffer, SymbolTable(values: values));
return buffer.toString();
}

View file

@ -18,7 +18,7 @@ void main() {
foo
.getAttribute('yes')
.value
.compute(new SymbolTable(values: {'no': 'maybe'})),
.compute(SymbolTable(values: {'no': 'maybe'})),
'maybe');
});

View file

@ -15,13 +15,13 @@ main() {
</html>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
jael.Document document;
SymbolTable scope;
try {
document = jael.parseDocument(template, sourceUrl: 'test.jael');
scope = new SymbolTable<dynamic>(values: {
scope = SymbolTable<dynamic>(values: {
'csrf_token': 'foo',
'profile': {
'avatar': 'thosakwe.png',
@ -64,10 +64,10 @@ main() {
</html>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
//jael.scan(template, sourceUrl: 'test.jael').tokens.forEach(print);
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable<dynamic>(values: {
var scope = SymbolTable<dynamic>(values: {
'pokemon': const _Pokemon('Darkrai', 'Dark'),
});
@ -105,9 +105,9 @@ main() {
</html>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable<dynamic>(values: {
var scope = SymbolTable<dynamic>(values: {
'starters': starters,
});
@ -150,9 +150,9 @@ main() {
</html>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable<dynamic>(values: {
var scope = SymbolTable<dynamic>(values: {
'starters': starters,
});
@ -196,9 +196,9 @@ main() {
</div>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable();
var scope = SymbolTable();
const jael.Renderer().render(document, buf, scope);
print(buf);
@ -242,9 +242,9 @@ main() {
</div>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable();
var scope = SymbolTable();
const jael.Renderer().render(document, buf, scope);
print(buf);
@ -267,9 +267,9 @@ main() {
<button '(click)'="myEventHandler(\$event)"></button>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable();
var scope = SymbolTable();
const jael.Renderer().render(document, buf, scope);
print(buf);
@ -298,10 +298,10 @@ main() {
</switch>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable<dynamic>(values: {
'account': new _Account(isDisabled: true),
var scope = SymbolTable<dynamic>(values: {
'account': _Account(isDisabled: true),
});
const jael.Renderer().render(document, buf, scope);
@ -325,10 +325,10 @@ main() {
</switch>
''';
var buf = new CodeBuffer();
var buf = CodeBuffer();
var document = jael.parseDocument(template, sourceUrl: 'test.jael');
var scope = new SymbolTable<dynamic>(values: {
'account': new _Account(isDisabled: null),
var scope = SymbolTable<dynamic>(values: {
'account': _Account(isDisabled: null),
});
const jael.Renderer().render(document, buf, scope);
@ -338,10 +338,10 @@ main() {
});
}
const List<_Pokemon> starters = const [
const _Pokemon('Bulbasaur', 'Grass'),
const _Pokemon('Charmander', 'Fire'),
const _Pokemon('Squirtle', 'Water'),
const List<_Pokemon> starters = [
_Pokemon('Bulbasaur', 'Grass'),
_Pokemon('Charmander', 'Fire'),
_Pokemon('Squirtle', 'Water'),
];
class _Pokemon {

View file

@ -1,7 +1,7 @@
import 'package:matcher/matcher.dart';
import 'package:jael/src/ast/token.dart';
Matcher isToken(TokenType type, [String text]) => new _IsToken(type, text);
Matcher isToken(TokenType type, [String text]) => _IsToken(type, text);
class _IsToken extends Matcher {
final TokenType type;

View file

@ -19,7 +19,7 @@ class StatefulApp extends Component<_AppState> with _StatefulAppJaelTemplate {
Timer _timer;
StatefulApp() {
state =_AppState(ticks: 0);
state = _AppState(ticks: 0);
_timer = Timer.periodic(Duration(seconds: 1), (t) {
setState(state.copyWith(ticks: t.tick));
});

View file

@ -1,3 +1 @@
abstract class DomNode {
}
abstract class DomNode {}