diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dabdb75..d25c75cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,10 +17,10 @@ * Migrated json_god to 4.0.0 (13/13 tests passed) * Migrated angel_client to 4.0.0 (6/13 tests passed) * Migrated angel_websocket to 4.0.0 (2/3 tests passed) -* Updated test to 4.0.0 (1/1 test passed) +* Migrated test to 4.0.0 (1/1 test passed) * Added symbol_table and migrated to 2.0.0 (16/16 tests passed) * Migrated jael to 4.0.0 (20/20 tests passed) -* Updated jael_preprocessor to 3.0.0 (in progress) +* Migrated jael_preprocessor to 3.0.0 (5/5 tests passed) * Updated angel_jael to 3.0.0 (in progress) * Updated pub_sub to 3.0.0 (in progress) * Updated production to 2.0.0 (in progress) diff --git a/packages/jael/jael_preprocessor/example/main.dart b/packages/jael/jael_preprocessor/example/main.dart index 5f5fb8e8..b9cf691b 100644 --- a/packages/jael/jael_preprocessor/example/main.dart +++ b/packages/jael/jael_preprocessor/example/main.dart @@ -4,11 +4,11 @@ import 'package:file/file.dart'; import 'package:jael/jael.dart' as jael; import 'package:jael_preprocessor/jael_preprocessor.dart' as jael; -Future process( +Future process( jael.Document doc, Directory dir, errorHandler(jael.JaelError e)) { return jael.resolve(doc, dir, onError: errorHandler, patch: [ (doc, dir, onError) { - print(doc.root.children.length); + print(doc!.root.children.length); return doc; }, ]); diff --git a/packages/jael/jael_preprocessor/lib/jael_preprocessor.dart b/packages/jael/jael_preprocessor/lib/jael_preprocessor.dart index f554eff4..604aa85d 100644 --- a/packages/jael/jael_preprocessor/lib/jael_preprocessor.dart +++ b/packages/jael/jael_preprocessor/lib/jael_preprocessor.dart @@ -1,19 +1,20 @@ import 'dart:async'; import 'dart:collection'; +import 'package:collection/collection.dart' show IterableExtension; import 'package:file/file.dart'; import 'package:jael/jael.dart'; import 'package:symbol_table/symbol_table.dart'; /// Modifies a Jael document. -typedef FutureOr Patcher(Document document, - Directory currentDirectory, void onError(JaelError error)); +typedef FutureOr? Patcher(Document? document, + Directory currentDirectory, void onError(JaelError error)?); /// Expands all `block[name]` tags within the template, replacing them with the correct content. /// /// To apply additional patches to resolved documents, provide a set of [patch] /// functions. -Future resolve(Document document, Directory currentDirectory, - {void onError(JaelError error), Iterable patch}) async { +Future resolve(Document document, Directory currentDirectory, + {void onError(JaelError error)?, Iterable? patch}) async { onError ?? (e) => throw e; // Resolve all includes... @@ -25,7 +26,7 @@ Future resolve(Document document, Directory currentDirectory, if (patch?.isNotEmpty != true) return patched; - for (var p in patch) { + for (var p in patch!) { patched = await p(patched, currentDirectory, onError); } @@ -33,24 +34,29 @@ Future resolve(Document document, Directory currentDirectory, } /// Folds any `extend` declarations. -Future applyInheritance(Document document, Directory currentDirectory, - void onError(JaelError error), Iterable patch) async { +Future applyInheritance( + Document? document, + Directory currentDirectory, + void onError(JaelError error)?, + Iterable? patch) async { + if (document == null) { + return null; + } if (document.root.tagName.name != 'extend') { // This is not an inherited template, so just fill in the existing blocks. var root = replaceChildrenOfElement(document.root, {}, onError, true, false); - return new Document(document.doctype, root); + return Document(document.doctype, root); } var element = document.root; - var attr = - element.attributes.firstWhere((a) => a.name == 'src', orElse: () => null); + var attr = element.attributes.firstWhereOrNull((a) => a.name == 'src'); if (attr == null) { - onError(new JaelError(JaelErrorSeverity.warning, + onError!(JaelError(JaelErrorSeverity.warning, 'Missing "src" attribute in "extend" tag.', element.tagName.span)); return null; } else if (attr.value is! StringLiteral) { - onError(new JaelError( + onError!(JaelError( JaelErrorSeverity.warning, 'The "src" attribute in an "extend" tag must be a string literal.', element.tagName.span)); @@ -70,10 +76,10 @@ Future applyInheritance(Document document, Directory currentDirectory, var out = hierarchy?.root; if (out is! RegularElement) { - return hierarchy.rootDocument; + return hierarchy!.rootDocument; } - Element setOut(Element out, Map definedOverrides, + Element setOut(Element out, Map definedOverrides, bool anyTemplatesRemain) { var children = []; @@ -87,40 +93,40 @@ Future applyInheritance(Document document, Directory currentDirectory, } } - var root = hierarchy.root as RegularElement; - return new RegularElement(root.lt, root.tagName, root.attributes, root.gt, + var root = hierarchy!.root as RegularElement; + return RegularElement(root.lt, root.tagName, root.attributes, root.gt, children, root.lt2, root.slash, root.tagName2, root.gt2); } // Loop through all extends, filling in blocks. - while (hierarchy.extendsTemplates.isNotEmpty) { + while (hierarchy!.extendsTemplates.isNotEmpty) { var tmpl = hierarchy.extendsTemplates.removeFirst(); var definedOverrides = findBlockOverrides(tmpl, onError); if (definedOverrides == null) break; out = - setOut(out, definedOverrides, hierarchy.extendsTemplates.isNotEmpty); + setOut(out!, definedOverrides, hierarchy.extendsTemplates.isNotEmpty); } // Lastly, just default-fill any remaining blocks. - var definedOverrides = findBlockOverrides(out, onError); - if (definedOverrides != null) out = setOut(out, definedOverrides, false); + var definedOverrides = findBlockOverrides(out!, onError); + out = setOut(out, definedOverrides, false); // Return our processed document. - return new Document(document.doctype, out); + return Document(document.doctype, out); } } Map findBlockOverrides( - Element tmpl, void onError(JaelError e)) { + Element tmpl, void onError(JaelError e)?) { var out = {}; for (var child in tmpl.children) { - if (child is RegularElement && child.tagName?.name == 'block') { + if (child is RegularElement && child.tagName.name == 'block') { var name = child.attributes - .firstWhere((a) => a.name == 'name', orElse: () => null) + .firstWhereOrNull((a) => a.name == 'name') ?.value - ?.compute(new SymbolTable()) as String; - if (name?.trim()?.isNotEmpty == true) { + ?.compute(SymbolTable()) as String?; + if (name != null && name.trim().isNotEmpty == true) { out[name] = child; } } @@ -130,27 +136,31 @@ Map findBlockOverrides( } /// Resolves the document hierarchy at a given node in the tree. -Future resolveHierarchy(Document document, - Directory currentDirectory, void onError(JaelError e)) async { - var extendsTemplates = new Queue(); - String parent; +Future resolveHierarchy(Document document, + Directory currentDirectory, void onError(JaelError e)?) async { + var extendsTemplates = Queue(); + String? parent; - while (document != null && (parent = getParent(document, onError)) != null) { + Document? doc = document; + while (doc != null && (parent = getParent(doc, onError)) != null) { try { - extendsTemplates.addFirst(document.root); - var file = currentDirectory.childFile(parent); + extendsTemplates.addFirst(doc.root); + var file = currentDirectory.childFile(parent!); var parsed = parseDocument(await file.readAsString(), - sourceUrl: file.uri, onError: onError); - document = await resolveIncludes(parsed, currentDirectory, onError); + sourceUrl: file.uri, onError: onError)!; + + doc = await resolveIncludes(parsed, currentDirectory, onError); } on FileSystemException catch (e) { - onError(new JaelError( - JaelErrorSeverity.error, e.message, document.root.span)); + onError!( + JaelError(JaelErrorSeverity.error, e.message, document.root.span)); return null; } } - if (document == null) return null; - return new DocumentHierarchy(document, extendsTemplates); + if (doc == null) { + return null; + } + return DocumentHierarchy(doc, extendsTemplates); } class DocumentHierarchy { @@ -164,17 +174,16 @@ class DocumentHierarchy { Iterable replaceBlocks( Element element, - Map definedOverrides, - void onError(JaelError e), + Map definedOverrides, + void onError(JaelError e)?, bool replaceWithDefault, bool anyTemplatesRemain) { if (element.tagName.name == 'block') { - var nameAttr = element.attributes - .firstWhere((a) => a.name == 'name', orElse: () => null); - var name = nameAttr?.value?.compute(new SymbolTable()); + var nameAttr = element.attributes.firstWhereOrNull((a) => a.name == 'name'); + var name = nameAttr?.value?.compute(SymbolTable()); if (name?.trim()?.isNotEmpty != true) { - onError(new JaelError( + onError!(JaelError( JaelErrorSeverity.warning, 'This has no `name` attribute, and will be outputted as-is.', element.span)); @@ -190,7 +199,7 @@ Iterable replaceBlocks( onError, replaceWithDefault, anyTemplatesRemain); return [ - new RegularElement( + RegularElement( element.lt, element.tagName, element.attributes, @@ -209,7 +218,7 @@ Iterable replaceBlocks( return [element]; } } else { - return allChildrenOfRegularElement(definedOverrides[name], + return allChildrenOfRegularElement(definedOverrides[name]!, definedOverrides, onError, replaceWithDefault, anyTemplatesRemain); } } else if (element is SelfClosingElement) { @@ -225,7 +234,7 @@ Iterable replaceBlocks( Element replaceChildrenOfElement( Element el, Map definedOverrides, - void onError(JaelError e), + void onError(JaelError e)?, bool replaceWithDefault, bool anyTemplatesRemain) { if (el is RegularElement) { @@ -238,20 +247,20 @@ Element replaceChildrenOfElement( RegularElement replaceChildrenOfRegularElement( RegularElement el, - Map definedOverrides, - void onError(JaelError e), + Map definedOverrides, + void onError(JaelError e)?, bool replaceWithDefault, bool anyTemplatesRemain) { var children = allChildrenOfRegularElement( el, definedOverrides, onError, replaceWithDefault, anyTemplatesRemain); - return new RegularElement(el.lt, el.tagName, el.attributes, el.gt, children, + return RegularElement(el.lt, el.tagName, el.attributes, el.gt, children, el.lt2, el.slash, el.tagName2, el.gt2); } List allChildrenOfRegularElement( RegularElement el, - Map definedOverrides, - void onError(JaelError e), + Map definedOverrides, + void onError(JaelError e)?, bool replaceWithDefault, bool anyTemplatesRemain) { var children = []; @@ -269,18 +278,17 @@ List allChildrenOfRegularElement( } /// Finds the name of the parent template. -String getParent(Document document, void onError(JaelError error)) { +String? getParent(Document document, void onError(JaelError error)?) { var element = document.root; - if (element?.tagName?.name != 'extend') return null; + if (element.tagName.name != 'extend') return null; - var attr = - element.attributes.firstWhere((a) => a.name == 'src', orElse: () => null); + var attr = element.attributes.firstWhereOrNull((a) => a.name == 'src'); if (attr == null) { - onError(new JaelError(JaelErrorSeverity.warning, + onError!(JaelError(JaelErrorSeverity.warning, 'Missing "src" attribute in "extend" tag.', element.tagName.span)); return null; } else if (attr.value is! StringLiteral) { - onError(new JaelError( + onError!(JaelError( JaelErrorSeverity.warning, 'The "src" attribute in an "extend" tag must be a string literal.', element.tagName.span)); @@ -291,14 +299,22 @@ String getParent(Document document, void onError(JaelError error)) { } /// Expands all `include[src]` tags within the template, and fills in the content of referenced files. -Future resolveIncludes(Document document, Directory currentDirectory, - void onError(JaelError error)) async { - return new Document(document.doctype, - await _expandIncludes(document.root, currentDirectory, onError)); +Future resolveIncludes(Document? document, + Directory currentDirectory, void onError(JaelError error)?) async { + if (document == null) { + return null; + } + Element? rootElement = + await _expandIncludes(document.root, currentDirectory, onError); + if (rootElement != null) { + return Document(document.doctype, rootElement); + } else { + return null; + } } -Future _expandIncludes(Element element, Directory currentDirectory, - void onError(JaelError error)) async { +Future _expandIncludes(Element element, Directory currentDirectory, + void onError(JaelError error)?) async { if (element.tagName.name != 'include') { if (element is SelfClosingElement) return element; @@ -307,13 +323,17 @@ Future _expandIncludes(Element element, Directory currentDirectory, for (var child in element.children) { if (child is Element) { - expanded.add(await _expandIncludes(child, currentDirectory, onError)); + Element? includeElement = + await _expandIncludes(child, currentDirectory, onError); + if (includeElement != null) { + expanded.add(includeElement); + } } else { expanded.add(child); } } - return new RegularElement( + return RegularElement( element.lt, element.tagName, element.attributes, @@ -324,19 +344,18 @@ Future _expandIncludes(Element element, Directory currentDirectory, element.tagName2, element.gt2); } else { - throw new UnsupportedError( + throw UnsupportedError( 'Unsupported element type: ${element.runtimeType}'); } } - var attr = - element.attributes.firstWhere((a) => a.name == 'src', orElse: () => null); + var attr = element.attributes.firstWhereOrNull((a) => a.name == 'src'); if (attr == null) { - onError(new JaelError(JaelErrorSeverity.warning, + onError!(JaelError(JaelErrorSeverity.warning, 'Missing "src" attribute in "include" tag.', element.tagName.span)); return null; } else if (attr.value is! StringLiteral) { - onError(new JaelError( + onError!(JaelError( JaelErrorSeverity.warning, 'The "src" attribute in an "include" tag must be a string literal.', element.tagName.span)); @@ -346,10 +365,13 @@ Future _expandIncludes(Element element, Directory currentDirectory, var file = currentDirectory.fileSystem.file(currentDirectory.uri.resolve(src)); var contents = await file.readAsString(); - var doc = parseDocument(contents, sourceUrl: file.uri, onError: onError); - var processed = await resolve( + var doc = parseDocument(contents, sourceUrl: file.uri, onError: onError)!; + var processed = await (resolve( doc, currentDirectory.fileSystem.directory(file.dirname), - onError: onError); + onError: onError)); + if (processed == null) { + return null; + } return processed.root; } } diff --git a/packages/jael/jael_preprocessor/pubspec.yaml b/packages/jael/jael_preprocessor/pubspec.yaml index d0b1bbe4..7d73645d 100644 --- a/packages/jael/jael_preprocessor/pubspec.yaml +++ b/packages/jael/jael_preprocessor/pubspec.yaml @@ -1,19 +1,29 @@ name: jael_preprocessor -version: 3.0.0 +version: 4.0.0 description: A pre-processor for resolving blocks and includes within Jael templates. author: Tobe O homepage: https://github.com/angel-dart/jael/tree/master/jael_preprocessor publish_to: none environment: - sdk: '>=2.10.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: file: ^6.1.0 jael: git: url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x + ref: sdk-2.12.x_nnbd path: packages/jael/jael - symbol_table: ^2.0.0 + symbol_table: + git: + url: https://github.com/dukefirehawk/angel.git + ref: sdk-2.12.x_nnbd + path: packages/symbol_table + collection: ^1.15.0-nullsafety.4 dev_dependencies: code_buffer: - test: ^1.15.7 \ No newline at end of file + git: + url: https://github.com/dukefirehawk/angel.git + ref: sdk-2.12.x_nnbd + path: packages/code_buffer + + test: ^1.17.3 \ No newline at end of file diff --git a/packages/jael/jael_preprocessor/test/block_test.dart b/packages/jael/jael_preprocessor/test/block_test.dart index 6d7100f2..c429d85d 100644 --- a/packages/jael/jael_preprocessor/test/block_test.dart +++ b/packages/jael/jael_preprocessor/test/block_test.dart @@ -7,10 +7,10 @@ import 'package:symbol_table/symbol_table.dart'; import 'package:test/test.dart'; main() { - FileSystem fileSystem; + late FileSystem fileSystem; setUp(() { - fileSystem = new MemoryFileSystem(); + fileSystem = MemoryFileSystem(); // a.jl fileSystem.file('a.jl').writeAsStringSync('a.jl'); @@ -51,13 +51,13 @@ main() { test('blocks are replaced or kept', () async { var file = fileSystem.file('c.jl'); var original = jael.parseDocument(await file.readAsString(), - sourceUrl: file.uri, onError: (e) => throw e); - var processed = await jael.resolve( + sourceUrl: file.uri, onError: (e) => throw e)!; + var processed = await (jael.resolve( original, fileSystem.directory(fileSystem.currentDirectory), - onError: (e) => throw e); - var buf = new CodeBuffer(); - var scope = new SymbolTable(); - const jael.Renderer().render(processed, buf, scope); + onError: (e) => throw e)); + var buf = CodeBuffer(); + var scope = SymbolTable(); + const jael.Renderer().render(processed!, buf, scope); print(buf); expect( @@ -76,13 +76,13 @@ main() { test('block defaults are emitted', () async { var file = fileSystem.file('b.jl'); var original = jael.parseDocument(await file.readAsString(), - sourceUrl: file.uri, onError: (e) => throw e); - var processed = await jael.resolve( + sourceUrl: file.uri, onError: (e) => throw e)!; + var processed = await (jael.resolve( original, fileSystem.directory(fileSystem.currentDirectory), - onError: (e) => throw e); - var buf = new CodeBuffer(); - var scope = new SymbolTable(); - const jael.Renderer().render(processed, buf, scope); + onError: (e) => throw e)); + var buf = CodeBuffer(); + var scope = SymbolTable(); + const jael.Renderer().render(processed!, buf, scope); print(buf); expect( @@ -104,13 +104,13 @@ main() { () async { var file = fileSystem.file('d.jl'); var original = jael.parseDocument(await file.readAsString(), - sourceUrl: file.uri, onError: (e) => throw e); - var processed = await jael.resolve( + sourceUrl: file.uri, onError: (e) => throw e)!; + var processed = await (jael.resolve( original, fileSystem.directory(fileSystem.currentDirectory), - onError: (e) => throw e); - var buf = new CodeBuffer(); - var scope = new SymbolTable(); - const jael.Renderer().render(processed, buf, scope); + onError: (e) => throw e)); + var buf = CodeBuffer(); + var scope = SymbolTable(); + const jael.Renderer().render(processed!, buf, scope); print(buf); expect( @@ -129,13 +129,13 @@ main() { test('blocks within blocks', () async { var file = fileSystem.file('foxtrot.jl'); var original = jael.parseDocument(await file.readAsString(), - sourceUrl: file.uri, onError: (e) => throw e); - var processed = await jael.resolve( + sourceUrl: file.uri, onError: (e) => throw e)!; + var processed = await (jael.resolve( original, fileSystem.directory(fileSystem.currentDirectory), - onError: (e) => throw e); - var buf = new CodeBuffer(); - var scope = new SymbolTable(); - const jael.Renderer().render(processed, buf, scope); + onError: (e) => throw e)); + var buf = CodeBuffer(); + var scope = SymbolTable(); + const jael.Renderer().render(processed!, buf, scope); print(buf); expect( diff --git a/packages/jael/jael_preprocessor/test/include_test.dart b/packages/jael/jael_preprocessor/test/include_test.dart index 4b23bb11..8f6ca89e 100644 --- a/packages/jael/jael_preprocessor/test/include_test.dart +++ b/packages/jael/jael_preprocessor/test/include_test.dart @@ -7,10 +7,10 @@ import 'package:symbol_table/symbol_table.dart'; import 'package:test/test.dart'; main() { - FileSystem fileSystem; + late FileSystem fileSystem; setUp(() { - fileSystem = new MemoryFileSystem(); + fileSystem = MemoryFileSystem(); // a.jl fileSystem.file('a.jl').writeAsStringSync('a.jl'); @@ -25,12 +25,12 @@ main() { test('includes are expanded', () async { var file = fileSystem.file('c.jl'); var original = jael.parseDocument(await file.readAsString(), - sourceUrl: file.uri, onError: (e) => throw e); + sourceUrl: file.uri, onError: (e) => throw e)!; var processed = await jael.resolveIncludes(original, fileSystem.directory(fileSystem.currentDirectory), (e) => throw e); - var buf = new CodeBuffer(); - var scope = new SymbolTable(); - const jael.Renderer().render(processed, buf, scope); + var buf = CodeBuffer(); + var scope = SymbolTable(); + const jael.Renderer().render(processed!, buf, scope); print(buf); expect( diff --git a/packages/test/pubspec.yaml b/packages/test/pubspec.yaml index 37b5fa80..b4f1b63d 100644 --- a/packages/test/pubspec.yaml +++ b/packages/test/pubspec.yaml @@ -41,5 +41,5 @@ dependencies: path: packages/mock_request web_socket_channel: ^2.0.0 dev_dependencies: - test: ^1.17.1 + test: ^1.17.3