├── .gitignore ├── README.md ├── TODO.md ├── dart2ts ├── .gitignore ├── CHANGELOG.md ├── COPYING ├── README.md ├── UNLICENSE ├── analysis_options.yaml ├── bin │ └── dart2ts.dart ├── build.dart ├── lib │ ├── annotations.dart │ ├── dart2ts.dart │ └── src │ │ ├── build_utils.dart │ │ ├── code_generator.dart │ │ ├── commands.dart │ │ ├── deps_installer.dart │ │ ├── overrides.yml │ │ ├── parts │ │ ├── contexts.dart │ │ ├── overrides.dart │ │ ├── ts_simple_ast.dart │ │ └── type_manager.dart │ │ └── utils.dart ├── npm.config ├── package.json ├── pubspec.yaml └── test │ ├── e2e_test.dart │ └── e2e_test.js ├── docs └── NOTES.md ├── e2e_test ├── .analysis_options ├── .gitignore ├── .nvmrc ├── README.md ├── dart2ts.dart ├── index.html ├── lib │ ├── .gitignore │ ├── array_from.dart │ ├── assign_op.dart │ ├── async_methods.dart │ ├── catch_with_stack.dart │ ├── class_constructors.dart │ ├── enum.dart │ ├── expando.dart │ ├── exports.ts │ ├── extending_list.dart │ ├── field_array.dart │ ├── function_declaration.dart │ ├── index.dart │ ├── index.html │ ├── index.ts │ ├── initializers.dart │ ├── list_sample.dart │ ├── method_ref.dart │ ├── mini_html.dart │ ├── mixin.dart │ ├── nativewrapper.dart │ ├── operand_sample.dart │ ├── sample1.dart │ ├── sample2.dart │ ├── sample3.dart │ ├── sample4.dart │ ├── sample5.dart │ ├── sample_var.dart │ ├── simple_expression.dart │ ├── strange_prefix_case.dart │ ├── test.ts │ ├── test2.ts │ ├── test3.ts │ ├── test4.ts │ ├── test_anno.dart │ ├── test_async.dart │ ├── test_async_closure.dart │ ├── test_cascading.dart │ ├── test_declOrder.dart │ ├── test_initializers.dart │ ├── test_js_anno.dart │ ├── test_map.dart │ ├── test_operator.dart │ ├── test_strange.dart │ ├── test_stream.dart │ ├── test_stringCtor.dart │ ├── test_unicodeEscape.dart │ ├── tests.html │ └── try_catch.dart ├── package-lock.json ├── package.json ├── pubspec.yaml ├── tsconfig.json ├── webpack.config.js └── yarn.lock ├── polymer2 ├── .gitignore ├── dart2ts.dart ├── dist │ ├── .gitignore │ └── package.json ├── lib │ ├── .gitignore │ ├── polymer2.dart │ └── src │ │ ├── annotations.dart │ │ ├── element.dart │ │ └── polymer_support.dart ├── package.json ├── pubspec.yaml ├── tsconfig.json └── yarn.lock ├── polymer2_builder ├── lib │ ├── polymer2_builder.dart │ └── src │ │ └── builder.dart └── pubspec.yaml ├── polymer2_test ├── .gitignore ├── bower.json ├── build.dart ├── lib │ ├── .gitignore │ ├── index.html │ ├── myelement.dart │ ├── myelement.html │ └── myelement.init.dart ├── package.json ├── pubspec.yaml ├── tsconfig.json └── yarn.lock └── polymer_test ├── .gitignore ├── build.dart ├── dist ├── .gitignore └── index.html ├── lib ├── .gitignore ├── html_template.dart ├── index.html ├── mini_html.dart ├── myelement.dart └── polymer.dart ├── package.json ├── pubspec.yaml ├── tsconfig.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool/ 2 | .idea/ 3 | .packages 4 | .pub/ 5 | pubspec.lock 6 | *.iml 7 | *.sublime-project 8 | *.sublime-workspace 9 | package-lock.json 10 | .DS_Store 11 | node_modules 12 | test/screens 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dart2Ts : a better TS interface 2 | 3 | ``HIC SUNT DRACONES`` 4 | 5 | **Dart2Ts** is an highly experimental dart to typescript compiler. 6 | 7 | ## Why ? 8 | 9 | Because I'm tired of the current limits of `dartdevc`. Also translating dart to TS allows 10 | us to leverage the `tsc` to produce code that works on every browser and optimizing, ecc. 11 | 12 | ## Targets 13 | 14 | - obviously : semantic equivalence 15 | - Produce "natural" and readable TS code, just like how you would have written that same code in TS. 16 | - Make it simple to use that code from TS and vice versa, like: 17 | - Allow extending a dart2ts class from ts and vice versa. 18 | 19 | ### Anti-targets 20 | 21 | - main target is to make it work on web, so: 22 | - initially don't want to port any "platform specific" library, try to use only `@JS` 23 | - I don't care about `Isolate` and stuff like that 24 | 25 | ## What works 26 | 27 | At the moment only translating `e2e_test` project, that means: 28 | - basic function definition 29 | - invocation 30 | - import of other modules (only core and current package for now) 31 | - string interpolation 32 | - named constructors 33 | - class extension 34 | - calling named constructors 35 | - basic class definition 36 | - basic instance creation 37 | - named parameters 38 | - optional parameters 39 | - cascading 40 | - `(cond)?true:false` conditional expressions 41 | - this implicit reference for method invocation 42 | - calling `.first` psuedo accessor on a `List` (it's replaced by an extension method) 43 | - property 44 | - property accessor 45 | - top level variable 46 | - redir constructors 47 | - field initializers 48 | - field parameters 49 | - properties initializers 50 | 51 | - support for `@JS` annotation 52 | - **DART2TS** extension 53 | 54 | **note** 'e2e_test' project is now able to write on the HTML page !!! 55 | 56 | **UPDATE** : now even `package:html5` is compiling. Next step is to create a demo project using `package:html5` and demo it. 57 | 58 | ### Dart2TS extensions 59 | 60 | #### Estension to @JS annotation 61 | 62 | `@JS` can now be used to specify from which module the symbol should be loaded. Module path and name should be separated by the `'#'` character. 63 | Alternatively one can use the `@Module('modulepath')` to specify the module path and the `@JS('name')` annotation for the namespace only. 64 | When both (`'#'` char and `@Module` annotation) are used the latter wins. 65 | The final name is defined concatanating both module path and namespace path information from each enclosing element. For example 66 | 67 | ```dart 68 | @JS('module#myjslib') 69 | library mylib; 70 | 71 | @JS('submod#Thing') 72 | class That { 73 | 74 | } 75 | 76 | ``` 77 | 78 | or 79 | 80 | ```dart 81 | @JS('myjslib') 82 | @Module('module') 83 | library mylib; 84 | 85 | @JS('Thing') 86 | @Module('submod') 87 | class That { 88 | 89 | } 90 | 91 | ``` 92 | 93 | Will cause any reference to `That` to be translated as a reference to `myjslib.Thing` in module `module/submod`. 94 | 95 | To declare only the module and not a namespace use `@JS('module#')`. For example the following will associate the `$` top level variable 96 | to the `$` symbol exported by module `jquery`: 97 | 98 | ```dart 99 | @JS('jquery#') 100 | library mylib; 101 | 102 | @JS() 103 | Function $; 104 | 105 | ``` 106 | 107 | or 108 | 109 | ```dart 110 | @JS() 111 | @Module('jquery') 112 | library mylib; 113 | 114 | @JS() 115 | Function $; 116 | 117 | ``` 118 | 119 | `@JS` annotation can also be used to change the name of the corresponding native method or properties, thus allowing to resolve any name conflict between dart and TS 120 | (Notably the `is` static method inside a class used by polymer). 121 | 122 | ## Roadmap 123 | 124 | - ~~a better way to deal with @anonymous @js objects. For instance "new ShadowRootInit()" should become ="{mode:null,delegatesFocus:null}" or something like that.~~ 125 | - ~~using other libraries (easy)~~ 126 | - declare dep on both `pubspec.yaml` and `package.json` 127 | - build the dep and produce typelibs and js 128 | - when main project is built the already compiled is used for runtime and the dart as analysis 129 | - dart could be replaced by summaries or by generated "dart type lib" : a version of the original lib with only external declarations. 130 | - dart "typelibs" (libs with only declaration and all method declared external) (boring) 131 | - make class definition work (easy) 132 | 133 | 134 | - flow control statemets (easy) 135 | - for in 136 | - ~~for (x;y;z)~~ 137 | - ~~yield~~ 138 | - ~~return~~ 139 | - while 140 | - ~~do~~ 141 | - ecc. 142 | - exports (medium ? easy ?) 143 | - nullable expression (`??` operator `?=` operator) (super easy) 144 | - literals 145 | - array 146 | - map 147 | - symbol (map to symbol) 148 | - complete expression (boring) 149 | - whats missing ? 150 | - factory constructors (super easy) 151 | - `async`, `async*` (should be easy as TS supports 'em all) 152 | - ~~map Future to Promise (difficulty level ?!?)~~ 153 | - ~~manage scope reference to "this." things (boring)~~ 154 | - mixin (with polymer approach) (should be easy but no named constructor should be allowed) 155 | - `implements` (subtle , typescript implement of classes is the same of dart?) 156 | - ~~deal with "rewriting" some method calls, like : (tricky)~~ 157 | - List -> Array 158 | - Map -> {} 159 | - ~~deal with "@JS" things (easy)~~ 160 | 161 | - (*light*) dart_sdk port 162 | - collections (maybe tricky, expecially to maintain semantical compatibility) 163 | - package:html (easy) 164 | - what else ? (boh) 165 | 166 | ## Notes 167 | 168 | `Dart2TS` generated classes do not requires a top common class so it will be easy 169 | to implement native js classes extensions. DDC infact requires a `new` initializers 170 | on super classes otherwise it will complain in some circumstances (that's why 171 | we had to patch id in polymerize). 172 | 173 | ## Caveat 174 | 175 | When executed a second time it can throw. Probably a bug in `builder` package. 176 | A workaround is to remove the `.dart_tool` hidden folder inside the package folder you are building (it will 177 | be recreated in the next build). 178 | 179 | When launching `dart2ts` with the watch flag (`-w`) there's no problem. -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | - ~~handle function expression inside method correclty~~ 2 | - ~~now there's a problem with this, should use JS closures~~ 3 | - ~~test async stream~~ 4 | - complete collections 5 | - object literals 6 | - mixin 7 | - abstract class 8 | - ~~Promise ? Why ? (see sample4.dart)~~ 9 | - ~~toString~~ 10 | - extending an overridden ( => replaced by `overrides.yml`) method : example extending `map` method of a list should actually extend `$map` 11 | - operator inheritance 12 | - consistently handle hashCode and equals : this is hard .. 13 | - ~~repeatable iterables~~ 14 | - named and factory constructor for dynamic : call something similar to `invokeMethod` 15 | - ~~force async and async* return type~~ 16 | - ~~implement `sync*` and `async*` wrapping to `DartIterator` and `DartStream`.~~ 17 | - decoration for `.ts` native => add metadata to dartiterable and stream in 18 | order to be used correctly with `invokeMethod` and `readProperty`, ecc. 19 | - generate type descriptor when required 20 | - ~~refactory with normale class~~ 21 | - ~~generate descriptor for get set~~ 22 | - generate descr for constructor 23 | - use of named constructor to enable different signatures 24 | - ~~fix get set top level generation (and check normal too)~~ 25 | - add support for external typelib import 26 | - add extra annotation in `overrides.yml`: annotation can be added to external dart 27 | code using the `overrides.yml` file 28 | - using `overrides.yml` read from base dir 29 | - an "overrides.yml" files in the top level will be merged with the default 30 | this can be used to add annotation to external types. For example this can be 31 | used to add "@TS(generate:true)" to all the `polymer_element` wrappers. 32 | - ~~use destructuring for named args~~ (this cannot be done because of optional not allowed for destructured arg) 33 | - method as generators 34 | - ~~support for string interpolation~~ 35 | - ~~support for far args mapping (@varargs)~~ 36 | - ~~in external calls just use "..." operator when calling :~~ 37 | - `pippo([a,b,c])` => `pippo(...[a,b,c])` 38 | - exporting only the definition tagged with `@TS(export='')` instead of the whole lib 39 | - export and import the definition (in order to be used also locally) 40 | -------------------------------------------------------------------------------- /dart2ts/.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool/ 2 | .idea/ 3 | .packages 4 | .pub/ 5 | pubspec.lock 6 | *.iml 7 | *.sublime-project 8 | *.sublime-workspace 9 | package-lock.json 10 | .DS_Store 11 | node_modules 12 | test/screens 13 | -------------------------------------------------------------------------------- /dart2ts/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### v0.9.15 2 | - Fixed wrong prefix op overrides (some are user definable ...) 3 | - Introduction to class interfaces ( == class interface with no constructors) 4 | 5 | ### v0.9.14 6 | - fixed issue with multiple fields init 7 | - better handling of static methods on native types 8 | - better ordering of emitted declaration 9 | - missing not operator 10 | - better handling of constructors for native types (string) 11 | - prefix and postfix operator not user definable 12 | 13 | ### v0.9.13 14 | - fixed string escape nasty bug 15 | 16 | ### v0.9.12 17 | - better support for try catch with type clause 18 | - completed dart type name mapping 19 | - added option to specify an overrides yaml file 20 | 21 | ### v0.9.11 22 | - fixed little bug when translating async closures. 23 | 24 | ### v0.9.10 25 | 26 | - null aware operator support 27 | -------------------------------------------------------------------------------- /dart2ts/COPYING: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polymer-dart/dart2ts/c8af292227e9638adae3e3cea4793da350566a91/dart2ts/COPYING -------------------------------------------------------------------------------- /dart2ts/README.md: -------------------------------------------------------------------------------- 1 | # TLDR 2 | 3 | *Dart2TS* is a dart1.x to typescript compiler. 4 | 5 | # Usage 6 | 7 | Install the tool : 8 | 9 | pub global activate dart2ts 10 | 11 | Launch it: 12 | 13 | dart2ts build 14 | 15 | # Package Requirements 16 | 17 | The package to translate should be in strong mode with all the dependencies resolved. 18 | 19 | The stronger it is the better dart2ts can understand it and translate it. 20 | 21 | # Details 22 | 23 | *Dart2TS* is a new approach of developing with Dart. You can write actual dart code and have it translated 24 | to effective typescript code. From there you can continue writing in dart or switch to typescript. 25 | 26 | The main advantages of using dart2ts instead of the traditional `dart2js` or `dartdevc` compilers is a 27 | better integration with the javascript / typescript / nodejs ecosystem. 28 | 29 | You can end up writing nodejs packages or webpack application using dart. 30 | 31 | # What is working 32 | 33 | Pretty much every constructs from dart1.x: 34 | 35 | - named constructors 36 | - factory constructors 37 | - async await 38 | - generators 39 | - named parameters 40 | 41 | # Help 42 | 43 | If you want to help you're welcome. These are some of the things that needs some helps: 44 | 45 | - improve code coverage 46 | - test 47 | - improve incremental building 48 | - port to dart2.0 49 | 50 | # Dart core libraries 51 | 52 | Dart core libraries (`dart:core`, `dart:async`) are been ported to typescript and are 53 | available [here](https://npm.dart-polymer.com/#/detail/@dart2ts/dart). 54 | 55 | In order to access dart2ts node packages you'll have add the following registers to your configuration: 56 | 57 | npm config set @dart2ts.packages:registry=https://npm.dart-polymer.com 58 | npm config set @dart2ts:registry=https://npm.dart-polymer.com 59 | 60 | 61 | -------------------------------------------------------------------------------- /dart2ts/UNLICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/polymer-dart/dart2ts/c8af292227e9638adae3e3cea4793da350566a91/dart2ts/UNLICENSE -------------------------------------------------------------------------------- /dart2ts/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | strong-mode: true 3 | # language: 4 | # enableConditionalDirectives: true 5 | exclude: 6 | - bazel-*/** 7 | - gen/** 8 | - polymer2 9 | - polymer2_builder 10 | - polymer2_test 11 | - polymer_test 12 | -------------------------------------------------------------------------------- /dart2ts/bin/dart2ts.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:dart2ts/src/commands.dart' as cmd; 3 | import 'package:logging/logging.dart'; 4 | 5 | const String BOLD = '\x1b[1m'; 6 | const String DIM = '\x1b[2m'; 7 | const String UNDERLINED = '\x1b[4m'; 8 | const String BLINK = '\x1b[5m'; 9 | const String REVERSE = '\x1b[7m'; 10 | const String NORMAL = '\x1b[0m'; 11 | 12 | Future main(List args) => cmd.main(args); 13 | -------------------------------------------------------------------------------- /dart2ts/build.dart: -------------------------------------------------------------------------------- 1 | import 'package:build_runner/build_runner.dart'; 2 | import 'package:dart2ts/dart2ts.dart'; 3 | import 'dart:io'; 4 | 5 | main() { 6 | Directory dir = new Directory('dart_sdl/.dart_tool'); 7 | if (dir.existsSync()) dir.deleteSync(recursive: true); 8 | build([ 9 | new BuildAction(new Dart2TsBuilder(/*new Config(moduleSuffix: '.js')*/), 'dart_sdk', inputs: ['lib/**.dart']), 10 | ], deleteFilesByDefault: true); 11 | } 12 | -------------------------------------------------------------------------------- /dart2ts/lib/annotations.dart: -------------------------------------------------------------------------------- 1 | class Module { 2 | final String path; 3 | final bool export; 4 | 5 | const Module(this.path, {this.export: false}); 6 | } 7 | 8 | class TargetLib { 9 | final String package; 10 | final String path; 11 | 12 | const TargetLib({this.package, this.path}); 13 | } 14 | 15 | class TS { 16 | final bool generate; 17 | final String typelib; 18 | final bool stringInterpolation; 19 | final String export; 20 | 21 | const TS({this.generate: false, this.typelib, this.stringInterpolation: false, this.export}); 22 | } 23 | 24 | class VarArgs { 25 | const VarArgs(); 26 | } 27 | 28 | class OnModuleLoad { 29 | const OnModuleLoad(); 30 | } 31 | 32 | const OnModuleLoad onModuleLoad = const OnModuleLoad(); 33 | 34 | const VarArgs varargs = const VarArgs(); 35 | -------------------------------------------------------------------------------- /dart2ts/lib/dart2ts.dart: -------------------------------------------------------------------------------- 1 | export 'package:dart2ts/src/code_generator.dart' show Dart2TsBuilder, Config,dart2tsBuild,dart2tsWatch,IOverrides; 2 | export 'package:dart2ts/src/build_utils.dart'; 3 | -------------------------------------------------------------------------------- /dart2ts/lib/src/build_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'dart:io'; 4 | import 'package:build_runner/build_runner.dart' as builder; 5 | 6 | import 'package:dart2ts/src/code_generator.dart'; 7 | 8 | import 'package:path/path.dart' as p; 9 | 10 | final p.Context path = p.url; 11 | 12 | npm([List args = const ['run', 'build']]) async { 13 | Process npm = await Process.start('npm', args); 14 | stdout.addStream(npm.stdout); 15 | stderr.addStream(npm.stderr); 16 | int exitCode = await npm.exitCode; 17 | if (exitCode != 0) { 18 | throw "Build error"; 19 | } 20 | } 21 | 22 | tsc({String basePath: '.'}) async { 23 | Process npm = await Process.start('npm run build', [], workingDirectory: basePath); 24 | stdout.addStream(npm.stdout); 25 | stderr.addStream(npm.stderr); 26 | int exitCode = await npm.exitCode; 27 | if (exitCode != 0) { 28 | throw "Build error"; 29 | } 30 | } 31 | 32 | enum Mode { APPLICATION, LIBRARY } 33 | 34 | class BuildException { 35 | builder.BuildResult _result; 36 | 37 | BuildException(this._result); 38 | 39 | builder.BuildResult get result => _result; 40 | 41 | toString() => "Build Exception ${_result.exception}"; 42 | } 43 | 44 | Future tsbuild({String basePath: '.', bool clean: true, Mode mode: Mode.LIBRARY}) async { 45 | if (clean) { 46 | Directory dir = new Directory(path.join(basePath, '.dart_tool')); 47 | if (dir.existsSync()) dir.deleteSync(recursive: true); 48 | } 49 | 50 | builder.PackageGraph packageGraph = new builder.PackageGraph.forPath(basePath); 51 | 52 | Config cfg; 53 | 54 | switch (mode) { 55 | case Mode.LIBRARY: 56 | cfg = new Config(modulePrefix: 'node_modules'); 57 | break; 58 | case Mode.APPLICATION: 59 | cfg = new Config(); 60 | break; 61 | } 62 | 63 | builder.BuildResult res = await builder.build([ 64 | new builder.BuildAction(new Dart2TsBuilder(cfg), packageGraph.root.name, inputs: ['lib/**.dart']), 65 | ], deleteFilesByDefault: true, packageGraph: packageGraph); 66 | 67 | if (res.status != builder.BuildStatus.success) { 68 | throw new BuildException(res); 69 | } 70 | 71 | await tsc(basePath: basePath); 72 | 73 | switch (mode) { 74 | case Mode.LIBRARY: 75 | await finishLibrary(basePath: basePath, packageName: packageGraph.root.name); 76 | break; 77 | case Mode.APPLICATION: 78 | break; 79 | } 80 | 81 | return res; 82 | } 83 | 84 | Future fixDependencyPath(String dist, String packageName) async { 85 | // Replace "node_modules" with relative url 86 | 87 | RegExp re = new RegExp("import([^\"']*)[\"']([^\"']*)[\"']"); 88 | await for (FileSystemEntity f in new Directory(dist).list(recursive: true)) { 89 | if (f is File) { 90 | List lines = await f.readAsLines(); 91 | IOSink sink = f.openWrite(); 92 | lines.map((l) { 93 | Match m = re.matchAsPrefix(l); 94 | if (m != null && (!path.isAbsolute(m[2]) && !m[2].startsWith('.'))) { 95 | String origPath = m[2]; 96 | String virtualAbsolutePath = 97 | path.joinAll(["node_modules", packageName]..addAll(path.split(path.relative(f.path, from: dist)))); 98 | String virtualRelativePath = path.relative(m[2], from: virtualAbsolutePath); 99 | // Compute relative path from "virtual" directory "node_modules//current_path" 100 | 101 | l = "import${m[1]}'${virtualRelativePath}';"; 102 | } 103 | 104 | return l; 105 | }).forEach((l) => sink.writeln(l)); 106 | 107 | await sink.close(); 108 | } 109 | } 110 | } 111 | 112 | Future copyAssets(String dist, {String basePath: '.'}) async { 113 | // Copy assets 114 | String srcPath = path.join(basePath, 'lib'); 115 | 116 | await for (FileSystemEntity f in new Directory(srcPath).list(recursive: true)) { 117 | if (f is File && !f.path.endsWith('.dart') && !f.path.endsWith('.ts')) { 118 | File d = new File(path.join(dist, path.relative(f.path, from: srcPath))); 119 | if (!d.parent.existsSync()) { 120 | await d.parent.create(recursive: true); 121 | } 122 | await f.copy(d.path); 123 | } 124 | } 125 | } 126 | 127 | Future finishLibrary({String basePath: '.', String packageName}) async { 128 | File tsconfigFile = new File(path.join(basePath, 'tsconfig.json')); 129 | var tsconfig = JSON.decode(tsconfigFile.readAsStringSync()); 130 | String dist = path.joinAll([basePath, tsconfig['compilerOptions']['outDir'], 'lib']); 131 | await fixDependencyPath(dist, packageName); 132 | await copyAssets(dist); 133 | } 134 | -------------------------------------------------------------------------------- /dart2ts/lib/src/code_generator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:analyzer/analyzer.dart'; 4 | import 'package:analyzer/dart/ast/token.dart'; 5 | import 'package:analyzer/dart/constant/value.dart'; 6 | import 'package:analyzer/dart/element/element.dart'; 7 | import 'package:analyzer/dart/element/type.dart'; 8 | import 'package:analyzer/src/dart/element/element.dart'; 9 | import 'package:analyzer/src/dart/element/member.dart'; 10 | import 'package:analyzer/src/generated/constant.dart'; 11 | import 'package:analyzer/src/generated/resolver.dart'; 12 | import 'package:args/command_runner.dart'; 13 | import 'package:build/build.dart'; 14 | import 'package:build_runner/build_runner.dart'; 15 | import 'package:dart2ts/src/utils.dart'; 16 | import 'package:logging/logging.dart'; 17 | import 'package:path/path.dart' as _P; 18 | import 'package:resource/resource.dart' as res; 19 | import 'package:source_gen/source_gen.dart'; 20 | import 'package:yaml/yaml.dart'; 21 | import 'dart:io' as io; 22 | 23 | part 'package:dart2ts/src/parts/contexts.dart'; 24 | 25 | part 'package:dart2ts/src/parts/ts_simple_ast.dart'; 26 | 27 | part 'parts/type_manager.dart'; 28 | 29 | part 'parts/overrides.dart'; 30 | 31 | final _P.Context path = new _P.Context(style: _P.Style.posix, current: '/'); 32 | 33 | /** 34 | * Second version of the code generator. 35 | */ 36 | 37 | Logger _logger = new Logger('dart2ts.lib.code_generator'); 38 | 39 | class Dart2TsBuildCommand extends Command { 40 | @override 41 | String get description => "Build a file"; 42 | 43 | @override 44 | String get name => 'build'; 45 | 46 | Dart2TsBuildCommand() { 47 | this.argParser 48 | ..addOption('dir', defaultsTo: '.', abbr: 'd', help: 'the base path of the package to process') 49 | ..addOption('sdk-prefix', defaultsTo: '@dart2ts/dart', help: 'The absolute module prefix') 50 | ..addOption('module-prefix', defaultsTo: '@dart2ts.packages', help: 'The absolute module prefix') 51 | ..addOption('module-suffix', defaultsTo: '', help: 'The modules suffix') 52 | ..addOption('with-overrides', abbr: 'o', help: 'Overrides file to use') 53 | ..addFlag('watch', abbr: 'w', defaultsTo: false, help: 'watch for changes'); 54 | } 55 | 56 | @override 57 | run() { 58 | PackageGraph graph = new PackageGraph.forPath(argResults['dir']); 59 | 60 | Overrides overrides; 61 | if (argResults['with-overrides'] != null) { 62 | YamlDocument doc = loadYamlDocument(new io.File(argResults['sdk-prefix']).readAsStringSync()); 63 | overrides = new Overrides(doc); 64 | } else { 65 | overrides = null; 66 | } 67 | 68 | List actions = [ 69 | new BuildAction( 70 | new Dart2TsBuilder(new Config( 71 | modulePrefix: argResults['module-prefix'], 72 | moduleSuffix: argResults['module-suffix'], 73 | overrides: overrides, 74 | sdkPrefix: argResults['sdk-prefix'])), 75 | graph.root.name, 76 | inputs: ['lib/**.dart', 'web/**.dart']) 77 | ]; 78 | 79 | if (argResults['watch'] == true) { 80 | watch(actions, packageGraph: graph, onLog: (_) {}, deleteFilesByDefault: true); 81 | } else { 82 | build(actions, packageGraph: graph, onLog: (_) {}, deleteFilesByDefault: true); 83 | } 84 | } 85 | } 86 | 87 | Future dart2tsBuild(String path, Config config) { 88 | PackageGraph graph = new PackageGraph.forPath(path); 89 | 90 | List actions = [ 91 | new BuildAction(new Dart2TsBuilder(config), graph.root.name, inputs: ['lib/**.dart', 'web/**.dart']) 92 | ]; 93 | 94 | return build(actions, packageGraph: graph, onLog: (_) {}, deleteFilesByDefault: true); 95 | } 96 | 97 | Future dart2tsWatch(String path, Config config) { 98 | PackageGraph graph = new PackageGraph.forPath(path); 99 | 100 | List actions = [ 101 | new BuildAction(new Dart2TsBuilder(config), graph.root.name, inputs: ['lib/**.dart', 'web/**.dart']) 102 | ]; 103 | 104 | return watch(actions, packageGraph: graph, onLog: (_) {}, deleteFilesByDefault: true); 105 | } 106 | 107 | Builder dart2TsBuilder([Config config]) { 108 | return new Dart2TsBuilder(config ?? new Config()); 109 | } 110 | 111 | /// A [Builder] wrapping on one or more [Generator]s. 112 | abstract class _BaseBuilder extends Builder { 113 | /// Wrap [_generators] to form a [Builder]-compatible API. 114 | _BaseBuilder() {} 115 | 116 | @override 117 | Future build(BuildStep buildStep) async { 118 | var resolver = buildStep.resolver; 119 | if (!await resolver.isLibrary(buildStep.inputId)) return; 120 | var lib = await buildStep.inputLibrary; 121 | 122 | await runWithContext(lib.context, () => generateForLibrary(lib, buildStep)); 123 | } 124 | 125 | Future generateForLibrary(LibraryElement library, BuildStep buildStep); 126 | 127 | @override 128 | Map> get buildExtensions => { 129 | '.dart': ['.ts'] 130 | }; 131 | } 132 | 133 | class Dart2TsBuilder extends _BaseBuilder { 134 | Config _config; 135 | 136 | Dart2TsBuilder([this._config]) { 137 | this._config ??= new Config(); 138 | } 139 | 140 | @override 141 | Future generateForLibrary(LibraryElement library, BuildStep buildStep) async { 142 | AssetId destId = new AssetId(buildStep.inputId.package, "${path.withoutExtension(buildStep.inputId.path)}.ts"); 143 | _logger.fine('Processing ${library.location} for ${destId}'); 144 | 145 | IndentingPrinter printer = new IndentingPrinter(); 146 | Overrides overrides = await Overrides.forCurrentContext(); 147 | if (_config.overrides != null) { 148 | overrides.merge(_config.overrides); 149 | } 150 | runWithContext(library.context, () { 151 | LibraryContext libraryContext = new LibraryContext(library, overrides, _config); 152 | 153 | libraryContext 154 | ..translate() 155 | ..tsLibrary.writeCode(printer); 156 | }); 157 | await buildStep.writeAsString(destId, printer.buffer); 158 | } 159 | } 160 | 161 | typedef void PrinterConsumer(IndentingPrinter p); 162 | 163 | /** 164 | * Printer 165 | */ 166 | 167 | class IndentingPrinter { 168 | int defaultIndent; 169 | StringBuffer _buffer = new StringBuffer(); 170 | 171 | int _currentIndent = 0; 172 | bool _newLine = true; 173 | 174 | IndentingPrinter({this.defaultIndent = 4}); 175 | 176 | void write(String some) { 177 | if (some?.isEmpty ?? true) { 178 | return; 179 | } 180 | 181 | if (_newLine) { 182 | _startLine(); 183 | } 184 | 185 | _buffer.write(some); 186 | } 187 | 188 | void _startLine() { 189 | _buffer.write(new String.fromCharCodes(new List.filled(_currentIndent, ' '.codeUnitAt(0)))); 190 | _newLine = false; 191 | } 192 | 193 | void indent([int count]) => _currentIndent += count ?? defaultIndent; 194 | 195 | void deindent([int count]) => _currentIndent -= count ?? defaultIndent; 196 | 197 | void indented(void consumer(IndentingPrinter), {int count}) { 198 | indent(count); 199 | consumer(this); 200 | deindent(count); 201 | } 202 | 203 | void writeln([String line = '']) { 204 | write(line); 205 | _buffer.writeln(); 206 | _newLine = true; 207 | } 208 | 209 | void accept(PrinterWriter w) => w == null ? this.write('/* ??? */') : w.writeCode(this); 210 | 211 | void join(Iterable writers, {String delim = ',', bool newLine = false}) { 212 | joinConsumers( 213 | writers.map((w) => (p) { 214 | p.accept(w); 215 | }), 216 | delim: delim, 217 | newLine: newLine); 218 | } 219 | 220 | void consume(PrinterConsumer c) => c(this); 221 | 222 | void joinConsumers(Iterable writers, {String delim = ',', bool newLine: false}) { 223 | bool first = true; 224 | writers.forEach((w) { 225 | if (!first) { 226 | write(delim); 227 | if (newLine) { 228 | writeln(); 229 | } 230 | } else { 231 | first = false; 232 | } 233 | this.consume(w); 234 | }); 235 | } 236 | 237 | String get buffer => _buffer.toString(); 238 | } 239 | 240 | abstract class PrinterWriter { 241 | void writeCode(IndentingPrinter printer); 242 | } 243 | -------------------------------------------------------------------------------- /dart2ts/lib/src/commands.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:args/command_runner.dart'; 3 | import 'package:dart2ts/src/deps_installer.dart' show Dart2TsInstallCommand; 4 | import 'package:logging/logging.dart'; 5 | import 'package:dart2ts/src/code_generator.dart' show Dart2TsBuildCommand; 6 | 7 | Logger _logger = new Logger('dart2ts.lib.command'); 8 | 9 | class Dart2TsCommandRunner extends CommandRunner { 10 | Dart2TsCommandRunner() : super('dart2ts', 'a better interface to TS') { 11 | addCommand(new Dart2TsBuildCommand()); 12 | addCommand(new Dart2TsInstallCommand()); 13 | } 14 | } 15 | 16 | const String BOLD = '\x1b[1m'; 17 | const String DIM = '\x1b[2m'; 18 | const String UNDERLINED = '\x1b[4m'; 19 | const String BLINK = '\x1b[5m'; 20 | const String REVERSE = '\x1b[7m'; 21 | const String NORMAL = '\x1b[0m'; 22 | 23 | Future main(List args) { 24 | Logger.root.level = Level.ALL; 25 | Logger.root.onRecord.listen((record) { 26 | print('${DIM}[${record.time}]${NORMAL} ' 27 | '${BOLD}${record.level}${NORMAL} ' 28 | '${record.loggerName}, ${record.message}'); 29 | if (record.error != null) { 30 | print("ERROR:\n${BLINK}${record.error}${NORMAL}"); 31 | print("STACKTRACE:\n${record.stackTrace??''}"); 32 | } 33 | }); 34 | return new Dart2TsCommandRunner().run(args); 35 | } -------------------------------------------------------------------------------- /dart2ts/lib/src/deps_installer.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'dart:io'; 4 | import 'package:args/command_runner.dart'; 5 | import 'package:build/src/builder/build_step.dart'; 6 | import 'package:build_runner/build_runner.dart'; 7 | import 'package:logging/logging.dart'; 8 | import 'package:package_config/packages_file.dart' as packages; 9 | import 'package:path/path.dart' as path; 10 | import 'package:yaml/yaml.dart'; 11 | 12 | Logger _logger = new Logger('dart2ts.lib.deps_installer'); 13 | 14 | class Pubspec { 15 | int depth; 16 | var content; 17 | String packagePath; 18 | 19 | List children = []; 20 | 21 | Pubspec({this.packagePath, this.content, this.depth}); 22 | 23 | String get name => content['name']; 24 | 25 | Map get dependencies => content['dependencies'] ?? {}; 26 | 27 | String get version => content['version'] ?? '0.0.0'; 28 | 29 | String get description => content['description'] ?? 'Package ${name}'; 30 | 31 | String get author => content['author'] ?? 'unknown'; 32 | 33 | toString() => "Package ${name} ${version} [${depth}]"; 34 | } 35 | 36 | class Dart2TsPackageBuildAction extends PackageBuilder { 37 | @override 38 | Future build(BuildStep buildStep) {} 39 | 40 | @override 41 | Iterable get outputs => ['dart2ts.gen.dart']; 42 | } 43 | 44 | class Dart2TsInstallCommand extends Command { 45 | @override 46 | String get description => "install dependencies"; 47 | 48 | @override 49 | String get name => 'install'; 50 | 51 | Dart2TsInstallCommand() { 52 | this.argParser 53 | ..addOption('dir', defaultsTo: '.', abbr: 'd', help: 'the base path of the package to process') 54 | ..addOption('out', defaultsTo: 'deps', abbr: 'o', help: 'install folder path'); 55 | } 56 | 57 | @override 58 | run() { 59 | String rootPath = argResults['dir']; 60 | String destPath = argResults['out']; 61 | 62 | // Load packages 63 | _installAllDeps(rootPath, destPath); 64 | } 65 | } 66 | 67 | void _installAllDeps(String rootPath, String destPath) { 68 | // Load packages 69 | File packagesFile = new File(path.join(rootPath, '.packages')); 70 | 71 | if (!packagesFile.existsSync()) { 72 | throw "`.packages` file is missing, please run `pub get`"; 73 | } 74 | 75 | // Read packages file 76 | Map pkgs = packages.parse(packagesFile.readAsBytesSync(), path.toUri(rootPath)); 77 | 78 | // Recursively collect all the NOT DEV DEPS 79 | 80 | Map deps = new Map(); 81 | 82 | Pubspec collectDeps(String fromPath, [int depth = 0]) { 83 | var content = loadYaml(new File(path.join(fromPath, 'pubspec.yaml')).readAsStringSync()); 84 | Pubspec pubspec = new Pubspec(packagePath: fromPath, content: content, depth: depth); 85 | if (!deps.containsKey(pubspec.name)) { 86 | deps[pubspec.name] = pubspec; 87 | (pubspec.dependencies ?? {}).keys.forEach((String k) { 88 | pubspec.children.add(collectDeps(path.dirname(pkgs[k].toFilePath()), depth + 1)); 89 | }); 90 | } 91 | 92 | return pubspec; 93 | } 94 | 95 | Pubspec rootSpec = collectDeps(rootPath); 96 | 97 | List sorted_deps = new List.from(deps.values.where((p) => p.packagePath != rootPath)) 98 | ..sort((p1, p2) => p1.depth.compareTo(p2.depth)); 99 | 100 | _logger.fine("Collected deps : ${sorted_deps}"); 101 | 102 | // All but root depth first 103 | Iterable depthFirst(Pubspec root) sync* { 104 | for (Pubspec child in root.children) { 105 | yield* depthFirst(child); 106 | } 107 | if (root != rootSpec) yield root; 108 | } 109 | 110 | depthFirst(rootSpec).forEach((p) { 111 | _logger.fine("Installing ${p.name} into ${destPath}"); 112 | _install(p, destPath); 113 | }); 114 | } 115 | 116 | void _install(Pubspec pubspec, String dest) { 117 | String packageDest = path.join(dest, pubspec.name); 118 | _copy(pubspec.packagePath, packageDest); 119 | 120 | // generate "package.json" 121 | 122 | _generatePackageJson(pubspec, dest, path.join(packageDest, 'package.json')); 123 | _generateTsConfig(pubspec, dest, path.join(packageDest, 'tsconfig.json')); 124 | } 125 | 126 | void _copy(String from, String to) { 127 | Directory src = new Directory(from); 128 | src.listSync(recursive: true).where((f) => f is File).forEach((e) { 129 | File f = e; 130 | String dest = path.join(to, path.relative(f.path, from: from)); 131 | new Directory(path.dirname(dest)).createSync(recursive: true); 132 | f.copySync(dest); 133 | }); 134 | } 135 | 136 | void _generatePackageJson(Pubspec pubspec, String pkgRoot, String filePath) { 137 | File f = new File(filePath); 138 | if (!f.existsSync()) { 139 | // Create a new file 140 | f.writeAsStringSync(JSON.encode({ 141 | "name": pubspec.name, 142 | "version": pubspec.version, 143 | "description": pubspec.description, 144 | "scripts": {"build": "tsc"}, 145 | "files": ["lib/**/*.js", "lib/**/*.d.ts", "package.json"], 146 | "author": pubspec.author, 147 | "license": "ISC", 148 | "dependencies": new Map.fromIterable(pubspec.children, 149 | key: (p) => p.name, value: (p) => path.relative(path.join(pkgRoot, p.name, 'dist'), from: f.parent.path)), 150 | "devDependencies": {"typescript": "^2.5.2"} 151 | })); 152 | } 153 | 154 | // copy it into dist too 155 | Directory dist = new Directory(path.join(f.parent.path, 'dist')); 156 | dist.createSync(recursive: true); 157 | 158 | f.copySync(path.join(dist.path, path.basename(f.path))); 159 | } 160 | 161 | void _generateTsConfig(Pubspec pubspec, String pkgRoot, String filePath) { 162 | File f = new File(filePath); 163 | if (!f.existsSync()) { 164 | // Create a new file 165 | f.writeAsStringSync(JSON.encode({ 166 | "compilerOptions": { 167 | "module": "es6", 168 | "target": "es6", 169 | "sourceMap": true, 170 | "declaration": true, 171 | "rootDir": "./lib/", 172 | "outDir": "dist", 173 | "baseUrl": "./", 174 | "experimentalDecorators": true, 175 | "lib": ["dom", "es6", "esnext.asynciterable"] 176 | }, 177 | "exclude": ["node_modules", "dist"], 178 | "include": ["lib/**/*.ts"], 179 | })); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /dart2ts/lib/src/overrides.yml: -------------------------------------------------------------------------------- 1 | overrides: 2 | "dart:async": 3 | from: "sdk:async" 4 | classes: 5 | Completer: 6 | to: 7 | class: DartCompleter 8 | Future: 9 | to: 10 | class: Future 11 | Stream: 12 | to: 13 | class: DartStream 14 | StreamSink: 15 | to: 16 | class: DartStreamSink 17 | StreamController: 18 | to: 19 | class: DartStreamController 20 | StreamSubscription: 21 | to: 22 | class: DartStreamSubscription 23 | StreamTransformer: 24 | to: 25 | class: DartStreamTransformer 26 | EventSink: 27 | to: 28 | class: DartEventSink 29 | Zone: 30 | to: 31 | class: DartZone 32 | ZoneSpecification: 33 | to: 34 | class: DartZoneSpecification 35 | Timer: 36 | to: 37 | class: DartTimer 38 | "dart:collection": 39 | from: "sdk:core" 40 | classes: 41 | ListMixin: 42 | to: 43 | class: DartListMixin 44 | ListBase: 45 | to: 46 | class: DartListBase 47 | HashMap: 48 | to: 49 | class: DartHashMap 50 | HashSet: 51 | to: 52 | class: DartHashSet 53 | UnmodifiableMapView: 54 | to: 55 | class: DartUnmodifiableMapView 56 | EfficientLengthIterable: 57 | to: 58 | class: DartEfficientLengthIterable 59 | SetMixin: 60 | to: 61 | class: DartSetMixin 62 | AbstractMap: 63 | to: 64 | class: AbstractDartMap 65 | ConstantMap: 66 | to: 67 | class: DartConstantMap 68 | LinkedHashSet: 69 | to: 70 | class: DartLinkedHashSet 71 | LinkedHashMap: 72 | to: 73 | class: DartLinkedHashMap 74 | ArrayIterator: 75 | to: 76 | class: DartArrayIterator 77 | ConstantMapView: 78 | to: 79 | class: DartConstantMapView 80 | EfficientLengthMappedIterable: 81 | to: 82 | class: DartEfficientLengthMappedIterable 83 | Error: 84 | to: 85 | class: DartError 86 | Es6LinkedHashMap: 87 | to: 88 | class: DartEs6LinkedHashMap 89 | ExpandIterable: 90 | to: 91 | class: DartExpandIterable 92 | ExpandIterator: 93 | to: 94 | class: DartExpandIterator 95 | IterableBase: 96 | to: 97 | class: DartIterableBase 98 | IterableMixin: 99 | to: 100 | class: DartIterableMixin 101 | JsLinkedHashMap: 102 | to: 103 | class: DartJsLinkedHashMap 104 | LinkedHashMapKeyIterable: 105 | to: 106 | class: DartLinkedHashMapKeyIterable 107 | LinkedHashMapKeyIterator: 108 | to: 109 | class: DartLinkedHashMapKeyIterator 110 | ListIterator: 111 | to: 112 | class: DartListIterator 113 | ListMapView: 114 | to: 115 | class: DartListMapView 116 | MapBase: 117 | to: 118 | class: DartMapBase 119 | MapMixin: 120 | to: 121 | class: DartMapMixin 122 | MappedIterable: 123 | to: 124 | class: DartMappedIterable 125 | MappedListIterable: 126 | to: 127 | class: DartMappedListIterable 128 | Primitives: 129 | to: 130 | class: DartPrimitives 131 | Random: 132 | to: 133 | class: DartRandom 134 | ReversedListIterable: 135 | to: 136 | class: DartReversedListIterable 137 | FixedLengthListMixin: 138 | to: 139 | class: DartFixedLengthListMixin 140 | SetBase: 141 | to: 142 | class: DartSetBase 143 | SkipIterable: 144 | to: 145 | class: DartSkipIterable 146 | SkipWhileIterable: 147 | to: 148 | class: DartSkipWhileIterable 149 | Sort: 150 | to: 151 | class: DartSort 152 | SubListIterable: 153 | to: 154 | class: DartSubListIterable 155 | TakeIterable: 156 | to: 157 | class: DartTakeIterable 158 | TakeWhileIterable: 159 | to: 160 | class: DartTakeWhileIterable 161 | UnmodifiableListBase: 162 | to: 163 | class: DartUnmodifiableListBase 164 | UnmodifiableListMixin: 165 | to: 166 | class: DartUnmodifiableListMixin 167 | WhereIterable: 168 | to: 169 | class: DartWhereIterable 170 | WhereIterator: 171 | to: 172 | class: DartWhereIterator 173 | Object: 174 | to: 175 | class: DartObject 176 | IntegerDivisionByZeroException: 177 | to: 178 | class: DartIntegerDivisionByZeroException 179 | Stopwatch: 180 | to: 181 | class: DartStopwatch 182 | Match: 183 | to: 184 | class: DartMatch 185 | BidirectionalIterator: 186 | to: 187 | class: DartBidirectionalIterator 188 | String: 189 | to: 190 | class: DartString 191 | StringMatch: 192 | to: 193 | class: DartStringMatch 194 | Runes: 195 | to: 196 | class: DartRunes 197 | RuneIterator: 198 | to: 199 | class: DartRuneIterator 200 | CodeUnits: 201 | to: 202 | class: DartCodeUnits 203 | Number: 204 | to: 205 | class: DartNumber 206 | Int: 207 | to: 208 | class: DartInt 209 | Double: 210 | to: 211 | class: DartDouble 212 | toIterable: 213 | to: 214 | class: toDartIterable 215 | MapView: 216 | to: 217 | class: DartMapView 218 | "dart:core": 219 | from: "sdk:core" 220 | classes: 221 | StackTrace: 222 | to: 223 | class: DartStackTrace 224 | ExceptionAndStackTrace: 225 | to: 226 | class: DartExceptionAndStackTrace 227 | Comparable: 228 | to: 229 | class: DartComparable 230 | DateTime: 231 | to: 232 | class: DartDateTime 233 | Uri: 234 | to: 235 | class: Uri 236 | from: "sdk:uri" 237 | StringBuffer: 238 | to: 239 | class: DartStringBuffer 240 | StringSink: 241 | to: 242 | class: DartStringSink 243 | Object: 244 | to: 245 | class: DartObject 246 | RegExp: 247 | to: 248 | class: DartRegExp 249 | Pattern: 250 | to: 251 | class: DartPattern 252 | Expando: 253 | to: 254 | class: DartExpando 255 | operators: 256 | "[]": "get" 257 | "[]=": "set" 258 | List: 259 | to: 260 | class: DartList 261 | Set: 262 | to: 263 | class: DartSet 264 | Map: 265 | to: 266 | class: DartMap 267 | operators: 268 | "[]": "get" 269 | "[]=": "set" 270 | Iterator: 271 | to: 272 | class: DartIterator 273 | Iterable: 274 | to: 275 | class: DartIterable 276 | Duration: 277 | to: 278 | class: DartDuration 279 | Sink: 280 | to: 281 | class: DartSink 282 | 283 | EfficientLengthIterable: 284 | to: 285 | class: DartEfficientLengthIterable 286 | SetMixin: 287 | to: 288 | class: DartSetMixin 289 | AbstractMap: 290 | to: 291 | class: AbstractDartMap 292 | ConstantMap: 293 | to: 294 | class: DartConstantMap 295 | HashSet: 296 | to: 297 | class: DartHashSet 298 | LinkedHashSet: 299 | to: 300 | class: DartLinkedHashSet 301 | LinkedHashMap: 302 | to: 303 | class: DartLinkedHashMap 304 | ArrayIterator: 305 | to: 306 | class: DartArrayIterator 307 | ConstantMapView: 308 | to: 309 | class: DartConstantMapView 310 | EfficientLengthMappedIterable: 311 | to: 312 | class: DartEfficientLengthMappedIterable 313 | Error: 314 | to: 315 | class: DartError 316 | Es6LinkedHashMap: 317 | to: 318 | class: DartEs6LinkedHashMap 319 | ExpandIterable: 320 | to: 321 | class: DartExpandIterable 322 | ExpandIterator: 323 | to: 324 | class: DartExpandIterator 325 | IterableBase: 326 | to: 327 | class: DartIterableBase 328 | IterableMixin: 329 | to: 330 | class: DartIterableMixin 331 | JsLinkedHashMap: 332 | to: 333 | class: DartJsLinkedHashMap 334 | LinkedHashMapKeyIterable: 335 | to: 336 | class: DartLinkedHashMapKeyIterable 337 | LinkedHashMapKeyIterator: 338 | to: 339 | class: DartLinkedHashMapKeyIterator 340 | ListIterator: 341 | to: 342 | class: DartListIterator 343 | ListMapView: 344 | to: 345 | class: DartListMapView 346 | MapBase: 347 | to: 348 | class: DartMapBase 349 | MapMixin: 350 | to: 351 | class: DartMapMixin 352 | MappedIterable: 353 | to: 354 | class: DartMappedIterable 355 | MappedListIterable: 356 | to: 357 | class: DartMappedListIterable 358 | Primitives: 359 | to: 360 | class: DartPrimitives 361 | Random: 362 | to: 363 | class: DartRandom 364 | ReversedListIterable: 365 | to: 366 | class: DartReversedListIterable 367 | FixedLengthListMixin: 368 | to: 369 | class: DartFixedLengthListMixin 370 | SetBase: 371 | to: 372 | class: DartSetBase 373 | SkipIterable: 374 | to: 375 | class: DartSkipIterable 376 | SkipWhileIterable: 377 | to: 378 | class: DartSkipWhileIterable 379 | Sort: 380 | to: 381 | class: DartSort 382 | SubListIterable: 383 | to: 384 | class: DartSubListIterable 385 | TakeIterable: 386 | to: 387 | class: DartTakeIterable 388 | TakeWhileIterable: 389 | to: 390 | class: DartTakeWhileIterable 391 | UnmodifiableListBase: 392 | to: 393 | class: DartUnmodifiableListBase 394 | UnmodifiableListMixin: 395 | to: 396 | class: DartUnmodifiableListMixin 397 | UnmodifiableMapView: 398 | to: 399 | class: DartUnmodifiableMapView 400 | WhereIterable: 401 | to: 402 | class: DartWhereIterable 403 | WhereIterator: 404 | to: 405 | class: DartWhereIterator 406 | IntegerDivisionByZeroException: 407 | to: 408 | class: DartIntegerDivisionByZeroException 409 | Stopwatch: 410 | to: 411 | class: DartStopwatch 412 | Match: 413 | to: 414 | class: DartMatch 415 | BidirectionalIterator: 416 | to: 417 | class: DartBidirectionalIterator 418 | StringMatch: 419 | to: 420 | class: DartStringMatch 421 | Runes: 422 | to: 423 | class: DartRunes 424 | RuneIterator: 425 | to: 426 | class: DartRuneIterator 427 | CodeUnits: 428 | to: 429 | class: DartCodeUnits 430 | toIterable: 431 | to: 432 | class: toDartIterable 433 | MapView: 434 | to: 435 | class: DartMapView -------------------------------------------------------------------------------- /dart2ts/lib/src/parts/overrides.dart: -------------------------------------------------------------------------------- 1 | part of '../code_generator.dart'; 2 | 3 | abstract class IOverrides { 4 | IOverrides(); 5 | 6 | factory IOverrides.parse(String overrideYaml) => new Overrides.parse(overrideYaml); 7 | } 8 | 9 | Map _recursiveMerge(Map map1, Map map2) { 10 | Set allKeys = new Set()..addAll(map1.keys)..addAll(map2.keys); 11 | 12 | return new Map.fromIterable(allKeys, value: (k) { 13 | if (map1[k] is Map || map2[k] is Map) { 14 | return _recursiveMerge(map1[k] ?? {}, map2[k] ?? {}) as V; 15 | } 16 | 17 | return map1[k] ?? map2[k]; 18 | }); 19 | } 20 | 21 | class Overrides extends IOverrides { 22 | Map _overrides; 23 | 24 | Map _libraryOverrides(String uri) => _overrides[uri] as Map; 25 | 26 | Overrides(YamlDocument _yaml) { 27 | Map _d = (_yaml?.contents is Map) ? _yaml.contents : {}; 28 | this._overrides = _d['overrides'] ?? {}; 29 | } 30 | 31 | factory Overrides.parse(String overrideYaml) { 32 | return new Overrides(loadYamlDocument(overrideYaml)); 33 | } 34 | 35 | static Future forCurrentContext() async { 36 | res.Resource resource = new res.Resource('package:dart2ts/src/overrides.yml'); 37 | String str = await resource.readAsString(); 38 | 39 | return new Overrides(loadYamlDocument(str)); 40 | } 41 | 42 | String resolvePrefix(TypeManager m, String module, [String origPrefix = null]) { 43 | if (module == 'global') { 44 | return ""; 45 | } else if (module != null) { 46 | if (module.startsWith('module:')) { 47 | return m.namespaceFor(uri: module, modulePath: module.substring(7)); 48 | } else if (module.startsWith('sdk:')) { 49 | return m.namespaceFor(uri: module, modulePath: module.substring(4),isSdk: true); 50 | } 51 | if (module.startsWith('dart:') || module.startsWith('package:')) { 52 | return m.namespace(getLibrary(currentContext, module)); 53 | } 54 | } else { 55 | return origPrefix; 56 | } 57 | } 58 | 59 | /** 60 | * Check for method overrides. 61 | * The target can be a method name or a square expression. Inside square expression one can use `${prefix}` to replace 62 | * with the current prefix for the destination module, in order to access static fields in the native class. 63 | */ 64 | TSExpression checkMethod(TypeManager typeManager, DartType type, String methodName, TSExpression tsTarget, 65 | {TSExpression orElse()}) { 66 | var classOverrides = _findClassOverride(type); 67 | 68 | if (classOverrides == null) { 69 | return orElse(); 70 | } 71 | 72 | String methodOverrides = (classOverrides['methods'] ?? {})[methodName]; 73 | 74 | if (methodOverrides == null) { 75 | return orElse(); 76 | } 77 | 78 | String module = classOverrides['to']['from']; 79 | 80 | String prefix = resolvePrefix(typeManager, module); 81 | 82 | // Square or dot ? 83 | 84 | if (methodOverrides.startsWith('[')) { 85 | String sym = methodOverrides.substring(1, methodOverrides.length - 1); 86 | sym = sym.replaceAllMapped(new RegExp(r"\${([^}]*)}"), (Match m) { 87 | String n = m.group(1); 88 | if (n == "prefix") { 89 | return prefix; 90 | } 91 | 92 | return "\${${n}}"; 93 | }); 94 | return new TSIndexExpression(tsTarget, new TSSimpleExpression(sym)); 95 | } else { 96 | return new TSDotExpression(tsTarget, methodOverrides); 97 | } 98 | } 99 | 100 | String checkProperty(TypeManager typeManager, DartType type, String name) { 101 | var classOverrides = _findClassOverride(type); 102 | 103 | if (classOverrides == null) { 104 | return name; 105 | } 106 | 107 | String propsOverrides = (classOverrides['properties'] ?? {})[name]; 108 | 109 | if (propsOverrides == null) { 110 | return name; 111 | } 112 | 113 | return propsOverrides; 114 | } 115 | 116 | Iterable _visitTypeHierarchy(DartType type, {bool recursive: true}) sync* { 117 | if (type == null) return; 118 | 119 | yield type; 120 | 121 | if (type == currentContext.typeProvider.objectType) return; 122 | 123 | if (!recursive) { 124 | return; 125 | } 126 | 127 | if (type.element is ClassElement) { 128 | yield* _visitTypeHierarchy((type.element as ClassElement).supertype, recursive: true); 129 | 130 | for (DartType intf in (type.element as ClassElement).interfaces) { 131 | yield* _visitTypeHierarchy(intf, recursive: true); 132 | } 133 | } 134 | } 135 | 136 | String findLibraryOverride(TypeManager tm, LibraryElement lib) { 137 | if (lib == null) { 138 | return null; 139 | } 140 | Uri fromUri = lib.source?.uri; 141 | 142 | _logger.fine("Checking type for {${fromUri}}"); 143 | if (fromUri == null) { 144 | return null; 145 | } 146 | 147 | var libOverrides = _libraryOverrides(fromUri.toString()); 148 | if (libOverrides == null) { 149 | return null; 150 | } 151 | 152 | String mod = libOverrides['from']; 153 | 154 | if (mod == null || !mod.startsWith('module:') && !mod.startsWith('sdk:')) { 155 | return null; 156 | } 157 | 158 | if (mod.startsWith('sdk:')) { 159 | return "${tm.sdkPrefix}/${mod.substring(4)}"; 160 | } 161 | return mod.substring(7); 162 | } 163 | 164 | _findClassOverride(DartType mainType, {bool recursive: true}) { 165 | return _visitTypeHierarchy(mainType, recursive: recursive).map((type) { 166 | LibraryElement from = type?.element?.library; 167 | Uri fromUri = from?.source?.uri; 168 | 169 | _logger.fine("Checking type for {${fromUri}}${type?.name}"); 170 | if (type == null || fromUri == null) { 171 | return null; 172 | } 173 | 174 | var libOverrides = _libraryOverrides(fromUri.toString()); 175 | if (libOverrides == null) { 176 | return null; 177 | } 178 | 179 | var classOverrides = (libOverrides['classes'] ?? {})[type.name]; 180 | if (classOverrides == null) { 181 | return null; 182 | } 183 | 184 | return new Map() 185 | ..addAll(classOverrides) 186 | ..putIfAbsent('library', () => libOverrides); 187 | }).firstWhere(notNull, orElse: () => null); 188 | } 189 | 190 | TSType checkType(TypeManager typeManager, String origPrefix, DartType type, bool noTypeArgs, {TSType orElse()}) { 191 | var classOverrides = _findClassOverride(type, recursive: false); 192 | 193 | if (classOverrides == null || classOverrides['to'] == null || (classOverrides['to'] as Map)['class'] == null) { 194 | return orElse(); 195 | } 196 | 197 | String module = classOverrides['to']['from'] ?? classOverrides['library']['from']; 198 | 199 | String p = resolvePrefix(typeManager, module, origPrefix); 200 | if (p != null && p.isNotEmpty) { 201 | p = "${p}."; 202 | } 203 | 204 | String actualName = classOverrides['to']['class']; 205 | 206 | if (!noTypeArgs && type is ParameterizedType && type.typeArguments.isNotEmpty) { 207 | return new TSGenericType("${p}${actualName}", type.typeArguments.map((t) => typeManager.toTsType(t)).toList()); 208 | } else { 209 | return new TSSimpleType("${p}${actualName}", !TypeManager.isNativeType(type)); 210 | } 211 | } 212 | 213 | TSExpression checkIndexedOperator( 214 | Context context, Expression target, Expression index, TSExpression orElse()) { 215 | var classOverrides = _findClassOverride(target?.bestType); 216 | 217 | if (classOverrides == null) return orElse(); 218 | 219 | var operators = classOverrides['operators']; 220 | 221 | bool isAssigning = isAssigningLeftSide(target.parent); 222 | 223 | String op; 224 | if (isAssigning) { 225 | op = "[]="; 226 | } else { 227 | op = "[]"; 228 | } 229 | 230 | if (operators == null || operators[op] == null) { 231 | return orElse(); 232 | } 233 | 234 | // replace with method invocation 235 | String methodName = operators[op]; 236 | 237 | if (isAssigning) { 238 | return new TSInvoke(new TSDotExpression(context.processExpression(target), methodName), [ 239 | context.processExpression(index), 240 | context.processExpression(assigningValue(target.parent)), 241 | ]); 242 | } else { 243 | return new TSInvoke( 244 | new TSDotExpression(context.processExpression(target), methodName), [context.processExpression(index)]); 245 | } 246 | } 247 | 248 | TSExpression checkConstructor(Context context, DartType targetType, ConstructorElement ctor, 249 | ArgumentListCollector collector, TSExpression orElse()) { 250 | var classOverrides = _findClassOverride(targetType); 251 | if (classOverrides == null || classOverrides['constructors'] == null) { 252 | return orElse(); 253 | } 254 | 255 | var constructor = classOverrides['constructors'][ctor.name ?? "\$default"]; 256 | if (constructor == null) { 257 | return orElse(); 258 | } 259 | 260 | String newName; 261 | bool isFactory; 262 | if (constructor is String) { 263 | newName = constructor; 264 | isFactory = false; 265 | } else { 266 | newName = constructor['name']; 267 | isFactory = constructor['factory']; 268 | } 269 | 270 | TSType tsType = context.typeManager.toTsType(targetType); 271 | 272 | return new TSInvoke(new TSStaticRef(tsType, newName), collector.arguments, collector.namedArguments) 273 | ..asNew = !isFactory; 274 | } 275 | 276 | void merge(Overrides newOverrides) { 277 | _overrides = _recursiveMerge(newOverrides._overrides, _overrides); 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /dart2ts/lib/src/parts/type_manager.dart: -------------------------------------------------------------------------------- 1 | part of '../code_generator.dart'; 2 | 3 | //const String SDK_LIBRARY = '@dart2ts/dart'; 4 | const String MODULE_PROPERTIES = 'properties'; 5 | 6 | class TSImport extends TSNode { 7 | String prefix; 8 | String path; 9 | LibraryElement library; 10 | List names; 11 | 12 | TSImport({this.prefix, this.path, this.library, this.names}) {} 13 | 14 | @override 15 | void writeCode(IndentingPrinter printer) { 16 | printer.write('import '); 17 | if (names == null || names.isEmpty) { 18 | printer.write('* as ${prefix}'); 19 | } else { 20 | printer.write('{'); 21 | printer.joinConsumers(names.map((name) => (p) => p.write(name))); 22 | printer.write('}'); 23 | } 24 | printer.writeln(' from "${path}";'); 25 | } 26 | } 27 | 28 | class TSPath { 29 | bool isJSAnnotated = false; 30 | List modulePathElements = []; 31 | List namespacePathElements = []; 32 | 33 | String get moduleUri => modulePathElements.isEmpty ? null : "module:${modulePath}"; 34 | 35 | String get modulePath => modulePathElements.join('/'); 36 | 37 | String get name => namespacePathElements.join('.'); 38 | 39 | void fixWindowAtFirst() { 40 | if (namespacePathElements.isNotEmpty && namespacePathElements.first == 'window') { 41 | namespacePathElements.removeAt(0); 42 | } 43 | } 44 | } 45 | 46 | class TypeManager { 47 | LibraryElement _current; 48 | Overrides _overrides; 49 | Set exports = new Set(); 50 | 51 | String modulePrefix; 52 | String moduleSuffix; 53 | String sdkPrefix; 54 | 55 | String resolvePath(String pp, {bool isSdk: false}) { 56 | if (!pp.startsWith('./')) { 57 | pp = path.normalize(path.join(isSdk ? sdkPrefix : modulePrefix, pp)); 58 | } 59 | return "${pp}${moduleSuffix}"; 60 | } 61 | 62 | TypeManager(this._current, this._overrides, {this.moduleSuffix, this.modulePrefix, this.sdkPrefix}) { 63 | _prefixes = {}; 64 | registerModule(String uri, String prefix, String modulePath, bool isSdk) { 65 | TSImport import = new TSImport(prefix: prefix, path: resolvePath(modulePath, isSdk: true)); 66 | _importedPaths[modulePath] = import; 67 | _prefixes[uri] = import; 68 | } 69 | 70 | registerSdkModule(String name) { 71 | registerModule("dart:${name}", name, name, true); 72 | } 73 | 74 | registerSdkModule('_common'); 75 | registerSdkModule('core'); 76 | registerSdkModule('async'); 77 | } 78 | 79 | Map _prefixes; 80 | 81 | String _nextPrefix() => "lib${_prefixes.length}"; 82 | 83 | AssetId _toAssetId(String uri) { 84 | if (uri.startsWith('asset:')) { 85 | List parts = path.split(uri.substring(6)); 86 | return new AssetId(parts.first, path.joinAll(parts.sublist(1))); 87 | } 88 | throw "Cannot convert to assetId : ${uri}"; 89 | } 90 | 91 | String namespace(LibraryElement lib) => namespaceFor(lib: lib); 92 | 93 | TSExpression checkMethod(DartType type, String methodName, TSExpression tsTarget, {TSExpression orElse()}) => 94 | _overrides.checkMethod(this, type, methodName, tsTarget, orElse: orElse); 95 | 96 | String checkProperty(DartType type, String name) => _overrides.checkProperty(this, type, name); 97 | 98 | TSImport _getSdkPath(String _name, {LibraryElement lib, List names, String modulePath}) { 99 | String name = _name.substring(5); 100 | 101 | String p = "${name}"; 102 | 103 | // Check if we are in dart_sdk and need relative paths for dart: imports 104 | DartObject anno = getAnnotation(_current.metadata, isTargetLib); 105 | if (anno != null) { 106 | String module = anno.getField('package').toStringValue(); 107 | String modPath = anno.getField('path').toStringValue(); 108 | if (module.startsWith('dart:')) { 109 | String my_path = path.join('/', modPath); 110 | p = path.relative(path.join('/', name), from: my_path); 111 | } 112 | } 113 | if (names != null) { 114 | return new TSImport(prefix: name, path: modulePath ?? resolvePath(p, isSdk: true), library: lib, names: names); 115 | } else { 116 | return _importedPaths.putIfAbsent(p, () { 117 | return new TSImport(prefix: name, path: modulePath ?? resolvePath(p, isSdk: true), library: lib); 118 | }); 119 | } 120 | } 121 | 122 | Map _importedPaths = {}; 123 | 124 | String namespaceFor({String uri, String modulePath, LibraryElement lib, bool isSdk: false}) { 125 | String overridePath =_overrides.findLibraryOverride(this, lib); 126 | modulePath = modulePath ?? overridePath; 127 | 128 | if (modulePath != null && _importedPaths.containsKey(modulePath)) { 129 | return _importedPaths[modulePath].prefix; 130 | } 131 | if (lib != null && lib == _current) { 132 | return null; 133 | } 134 | 135 | uri ??= lib.source.uri.toString(); 136 | 137 | if (uri == 'module:global') { 138 | return null; 139 | } 140 | 141 | return _prefixes.putIfAbsent(uri, () { 142 | if (lib == null) { 143 | assert(modulePath != null); 144 | return _importedPaths.putIfAbsent( 145 | modulePath, () => new TSImport(prefix: _nextPrefix(), path: resolvePath(modulePath, isSdk: isSdk))); 146 | } 147 | if (lib.isInSdk) { 148 | // Replace with ts_sdk 149 | 150 | return _getSdkPath(lib.name, lib: lib, modulePath: overridePath); 151 | } 152 | 153 | // If same package produce a relative path 154 | AssetId currentId = _toAssetId(_current.source.uri.toString()); 155 | AssetId id = _toAssetId(uri); 156 | 157 | String libPath; 158 | 159 | if (id.package == currentId.package) { 160 | libPath = 161 | path.joinAll(['.', path.withoutExtension(path.relative(id.path, from: path.dirname(currentId.path)))]); 162 | } else { 163 | libPath = path.join("${id.package}", "${path.withoutExtension(id.path)}"); 164 | } 165 | 166 | // Fix import for libs in subfolders for windows (this should not be necessary anymore as 167 | // path is now unix path everywhere ... but can't test it so I leave the "fix" 168 | libPath = libPath.replaceAll(path.separator, "/"); 169 | 170 | // Extract package name and path and produce a nodemodule path 171 | 172 | return _importedPaths.putIfAbsent( 173 | libPath, () => new TSImport(prefix: _nextPrefix(), path: resolvePath(libPath), library: lib)); 174 | }).prefix; 175 | } 176 | 177 | static final RegExp NAME_PATTERN = new RegExp('(([^#]+)#)?(.*)'); 178 | 179 | Iterable _elementsFromLibrary(Element e) sync* { 180 | if (e == null) { 181 | return; 182 | } 183 | 184 | if (e is! LibraryElement) { 185 | yield* _elementsFromLibrary(e.enclosingElement); 186 | } 187 | 188 | if (e is! CompilationUnitElement) { 189 | yield e; 190 | } 191 | } 192 | 193 | TSPath _collectJSPath(Element start) => _elementsFromLibrary(start).fold(new TSPath(), (p, e) { 194 | DartObject anno = getAnnotation(e.metadata, isJS); 195 | //if (anno == null) return p; 196 | p.isJSAnnotated = p.isJSAnnotated || (e is! LibraryElement && anno != null); 197 | 198 | // Collect if metadata 199 | String name = anno?.getField('name')?.toStringValue(); 200 | 201 | if (name != null && name.isNotEmpty) { 202 | Match m = NAME_PATTERN.matchAsPrefix(name); 203 | if ((m != null && m[2] != null)) { 204 | p.modulePathElements.add(m[2]); 205 | if ((m[3] ?? '').isNotEmpty) p.namespacePathElements.addAll(m[3].split('.')); 206 | } else { 207 | p.namespacePathElements.addAll(name.split('.')); 208 | } 209 | } else if (e == start) { 210 | // Add name if it's the first 211 | p.namespacePathElements.add(_name(e)); 212 | } 213 | 214 | // Process module path 215 | var moduleAnnotation = getAnnotation(e.metadata, isModule); 216 | String module = moduleAnnotation?.getField('path')?.toStringValue(); 217 | if (module != null) { 218 | p.modulePathElements.add(module); 219 | if (moduleAnnotation.getField('export')?.toBoolValue() ?? false) { 220 | exports.add(module); 221 | } 222 | } 223 | 224 | return p; 225 | }); 226 | 227 | static Set nativeTypes() => ((TypeProvider x) => new Set.from([ 228 | x.boolType, 229 | x.stringType, 230 | x.intType, 231 | x.numType, 232 | x.doubleType, 233 | x.functionType, 234 | ]))(currentContext.typeProvider); 235 | 236 | static Set nativeClasses = new Set.from(['List', 'Map', 'Iterable', 'Iterator']); 237 | 238 | static bool isNativeType(DartType t) => 239 | nativeTypes().contains(t) || 240 | (t.element?.library?.isDartCore ?? false) && (nativeClasses.contains(t.element?.name)); 241 | 242 | static String _name(Element e) => (e is PropertyAccessorElement) ? e.variable.name : e.name; 243 | 244 | String toTsName(Element element, {bool nopath: false}) { 245 | if (element == null) { 246 | return null; 247 | } 248 | 249 | TSPath jspath = _collectJSPath(element); // note: we should check if var is top, but ... whatever. 250 | 251 | // For top level elements (properties and methods) use namespace path and module path 252 | if (isTopLevel(element)) { 253 | String name; 254 | // In case of explicit namespaces use it 255 | if (jspath.isJSAnnotated) { 256 | if (jspath.modulePathElements.isNotEmpty) { 257 | bool isSdk = false; 258 | String modulePath = jspath.modulePath; 259 | if (modulePath.startsWith('sdk:')) { 260 | modulePath = "${modulePath.substring(4)}"; 261 | isSdk = true; 262 | } else if (modulePath.startsWith('package:')) { 263 | modulePath = "${modulePrefix}/${modulePath.substring(8)}"; 264 | } 265 | 266 | name = namespaceFor(uri: jspath.moduleUri, modulePath: modulePath, isSdk: isSdk) + "." + jspath.name; 267 | } else { 268 | name = jspath.name; 269 | } 270 | } else { 271 | // Use normal prefix + name otherwise , use also module for toplevel properties 272 | String m = (element is PropertyAccessorElement) ? "${MODULE_PROPERTIES}." : ""; 273 | String prefix = namespace(element.library); 274 | prefix = (prefix == null) ? "" : "${prefix}."; 275 | 276 | name = "${prefix}${m}${_name(element)}"; 277 | } 278 | 279 | return name; 280 | } 281 | 282 | // For class members use the name or js name only 283 | String name; 284 | // In case of explicit namespaces use it 285 | if (jspath.namespacePathElements.isNotEmpty) { 286 | name = jspath.namespacePathElements.last; 287 | } else { 288 | // Use normal prefix + name otherwise , use also module for toplevel properties 289 | name = _name(element); 290 | } 291 | 292 | return name; 293 | } 294 | 295 | static bool isTopLevel(Element e) => e.library.units.contains(e.enclosingElement); 296 | 297 | TSType toTsType(DartType type, {bool noTypeArgs: false, bool inTypeOf: false}) { 298 | if (type == null) { 299 | return null; 300 | } 301 | 302 | // Look for @JS annotations 303 | if (type is TypeParameterType) { 304 | return new TSSimpleType(type.element.name, !TypeManager.isNativeType(type)); 305 | } 306 | 307 | if (type is FunctionType) { 308 | Iterable args = () sync* { 309 | Map normalPars = new Map.fromIterables(type.normalParameterNames, type.normalParameterTypes); 310 | 311 | for (var p in type.normalParameterNames) { 312 | yield [p, toTsType(normalPars[p])]; 313 | } 314 | 315 | Map optionalPars = 316 | new Map.fromIterables(type.optionalParameterNames, type.optionalParameterTypes); 317 | for (var p in type.optionalParameterNames) { 318 | yield [p, new TSOptionalType(toTsType(optionalPars[p]))]; 319 | } 320 | 321 | if (type.namedParameterTypes.isNotEmpty) { 322 | yield [ 323 | NAMED_ARGUMENTS, 324 | new TSInterfaceType( 325 | fields: new Map.fromIterable(type.namedParameterTypes.keys, 326 | value: (k) => new TSOptionalType(toTsType(type.namedParameterTypes[k])))) 327 | ]; 328 | } 329 | }(); 330 | 331 | List typeArguments = 332 | new List.from(type.typeParameters?.map((t) => new TSTypeParameter(t.name, toTsType(t.bound)))); 333 | 334 | return new TSFunctionType( 335 | toTsType(type.returnType), new Map.fromIterable(args, key: (p) => p[0], value: (p) => p[1]), typeArguments); 336 | } 337 | 338 | if (getAnnotation(type?.element?.metadata ?? [], isJS) != null) { 339 | // check if we got a package annotation 340 | TSPath path = _collectJSPath(type.element); 341 | // Lookup for prefix 342 | String moduleUri = path.moduleUri; 343 | // ensure lib is always imported 344 | String libPrefix = namespace(type.element.library); 345 | String prefix; 346 | if (moduleUri != null) { 347 | prefix = namespaceFor(uri: path.moduleUri, modulePath: path.modulePath) + '.'; 348 | } else if ((getAnnotation(type.element.metadata, isTS)?.getField('export')?.toStringValue() ?? "").isNotEmpty) { 349 | // use lib prefix for this type if the class is exported from another module 350 | 351 | // TODO we could actually only export this class instead of the whole library ... but this is ok for now. 352 | prefix = "${libPrefix}."; 353 | } else { 354 | prefix = ''; 355 | } 356 | 357 | Iterable typeArgs; 358 | if (!noTypeArgs && type is ParameterizedType && type.typeArguments?.isNotEmpty ?? false) { 359 | typeArgs = ((type as ParameterizedType).typeArguments).map((t) => toTsType(t)); 360 | } else { 361 | typeArgs = null; 362 | } 363 | 364 | return new TSGenericType("${prefix}${path.name}", typeArgs); 365 | } 366 | 367 | if (type.isDynamic) { 368 | return new TSSimpleType("any", true); 369 | } 370 | 371 | String p; 372 | if (type.element != null && type.element.library != _current && !isNativeType(type)) { 373 | p = "${namespace(type.element.library)}."; 374 | } else { 375 | p = ""; 376 | } 377 | 378 | return _overrides.checkType(this, p, type, noTypeArgs, orElse: () { 379 | String actualName; 380 | if (type == currentContext.typeProvider.numType || type == currentContext.typeProvider.intType) { 381 | actualName = 'number'; 382 | } else if (type == currentContext.typeProvider.stringType) { 383 | actualName = 'string'; 384 | } else if (type == currentContext.typeProvider.boolType) { 385 | actualName = 'boolean'; 386 | } else { 387 | actualName = type.name; 388 | } 389 | 390 | if (nativeTypes().contains(type) && inTypeOf) { 391 | actualName = '"${actualName}"'; 392 | } 393 | 394 | if (!noTypeArgs && type is ParameterizedType && type.typeArguments.isNotEmpty) { 395 | return new TSGenericType("${p}${actualName}", type.typeArguments.map((t) => toTsType(t))); 396 | } else { 397 | return new TSSimpleType("${p}${actualName}", !TypeManager.isNativeType(type)); 398 | } 399 | }); 400 | } 401 | 402 | Iterable get allImports => _prefixes.values; 403 | 404 | String namespaceForPrefix(PrefixElement prefix) { 405 | return namespace(_current.getImportsWithPrefix(prefix).first.importedLibrary); 406 | } 407 | 408 | TSExpression checkIndexedOperator( 409 | Context context, Expression target, Expression index, TSExpression orElse()) => 410 | _overrides.checkIndexedOperator(context, target, index, orElse); 411 | 412 | TSExpression checkConstructor(Context context, DartType targetType, ConstructorElement ctor, 413 | ArgumentListCollector collector, TSExpression orElse()) => 414 | _overrides.checkConstructor(context, targetType, ctor, collector, orElse); 415 | } 416 | -------------------------------------------------------------------------------- /dart2ts/lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:analyzer/dart/element/type.dart'; 3 | import 'dart:io'; 4 | import 'package:analyzer/analyzer.dart'; 5 | import 'package:analyzer/dart/constant/value.dart'; 6 | import 'package:analyzer/dart/element/element.dart'; 7 | import 'package:analyzer/src/generated/engine.dart'; 8 | 9 | bool isListType(DartType type) => isTypeInstanceOf(type?.element?.context?.typeProvider?.listType, type); 10 | 11 | bool isIterableType(DartType type) => isTypeInstanceOf(type?.element?.context?.typeProvider?.iterableType, type); 12 | 13 | bool isTypeInstanceOf(ParameterizedType base, DartType type) => 14 | type != null && 15 | (type is ParameterizedType) && 16 | type.typeArguments.length == 1 && 17 | type.isSubtypeOf(base.instantiate([type.typeArguments.single])); 18 | 19 | final Uri _DART2TS_URI = Uri.parse('package:dart2ts/annotations.dart'); 20 | final Uri _DART2TS_ASSET_URI = Uri.parse('asset:dart2ts/lib/annotations.dart'); 21 | 22 | final Uri _POLYMER2_URI = Uri.parse('package:polymer2/src/annotations.dart'); 23 | final Uri _POLYMER2_ASSET_URI = Uri.parse('asset:polymer2/lib/src/annotations.dart'); 24 | 25 | final Uri _POLYMER_REGISTER_URI = Uri.parse('package:polymer_element/annotations.dart'); 26 | final Uri _POLYMER_REGISTER_ASSET_URI = Uri.parse('asset:polymer_element/lib/annotations.dart'); 27 | final Uri _JS_URI = Uri.parse('package:js/js.dart'); 28 | final Uri _JS_ASSET_URI = Uri.parse('asset:js/lib/js.dart'); 29 | 30 | final Uri _POLYMER_INIT_URI = Uri.parse('package:polymerize_common/init.dart'); 31 | final Uri _POLYMER_INIT_ASSET_URI = Uri.parse('asset:polymerize_common/lib/init.dart'); 32 | 33 | final Uri _POLYMER_MAP_URI = Uri.parse('package:polymerize_common/map.dart'); 34 | final Uri _POLYMER_MAP_ASSET_URI = Uri.parse('asset:polymerize_common/lib/map.dart'); 35 | 36 | final Uri _POLYMER_HTML_IMPORT_URI = Uri.parse('package:polymerize_common/html_import.dart'); 37 | final Uri _POLYMER_HTML_IMPORT_ASSET_URI = Uri.parse('asset:polymerize_common/lib/html_import.dart'); 38 | 39 | bool isDart2TsUri(Uri u) => u == _DART2TS_URI || u == _DART2TS_ASSET_URI; 40 | 41 | bool isJsUri(Uri u) => u == _JS_ASSET_URI || u == _JS_URI; 42 | 43 | bool isPolymerElementUri(Uri u) => u == _POLYMER_REGISTER_ASSET_URI || u == _POLYMER_REGISTER_URI; 44 | 45 | bool isPolymer2Uri(Uri u) => u == _POLYMER2_ASSET_URI || u == _POLYMER2_URI; 46 | 47 | bool isPolymerMapUri(Uri u) => u == _POLYMER_MAP_URI || u == _POLYMER_MAP_ASSET_URI; 48 | 49 | bool isPolymerElementInitUri(Uri u) => u == _POLYMER_INIT_URI || u == _POLYMER_INIT_ASSET_URI; 50 | 51 | bool isPolymerElementHtmlImportUri(Uri u) => u == _POLYMER_HTML_IMPORT_URI || u == _POLYMER_HTML_IMPORT_ASSET_URI; 52 | 53 | bool isJS(DartObject o) => (isJsUri(o.type.element.librarySource.uri)) && (o.type.name == 'JS'); 54 | 55 | bool isAnonymous(DartObject o) => (isJsUri(o.type.element.librarySource.uri)) && (o.type.name == '_Anonymous'); 56 | 57 | bool isModule(DartObject o) => (isDart2TsUri(o.type.element.librarySource.uri)) && (o.type.name == 'Module'); 58 | 59 | bool isTargetLib(DartObject o) => (isDart2TsUri(o.type.element.librarySource.uri) && (o.type.name == 'TargetLib')); 60 | 61 | bool isTS(DartObject o) => (isDart2TsUri(o.type.element.librarySource.uri) && (o.type.name == 'TS')); 62 | 63 | bool isVarargs(DartObject o) => (isDart2TsUri(o.type.element.librarySource.uri) && (o.type.name == 'VarArgs')); 64 | 65 | bool isOnModuleLoad(DartObject o) => 66 | (isDart2TsUri(o.type.element.librarySource.uri) && (o.type.name == 'OnModuleLoad')); 67 | 68 | bool isBowerImport(DartObject o) => 69 | o != null && (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'BowerImport'); 70 | 71 | bool isJsMap(DartObject o) => 72 | o != null && (isPolymerMapUri(o.type.element.librarySource.uri)) && (o.type.name == 'JsMap'); 73 | 74 | bool isDefine(DartObject o) => (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'Define'); 75 | 76 | bool isObserve(DartObject o) => (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'Observe'); 77 | 78 | bool isReduxActionFactory(DartObject o) => 79 | (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'ReduxActionFactory'); 80 | 81 | bool isProperty(DartObject o) => (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'Property'); 82 | 83 | bool isNotify(DartObject o) => (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'Notify'); 84 | 85 | bool isPolymerRegister(DartObject o) => 86 | o != null && (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'PolymerRegister'); 87 | 88 | bool isPolymerRegister2(DartObject o) => 89 | o != null && (isPolymer2Uri(o.type.element.librarySource.uri)) && (o.type.name == 'PolymerRegister'); 90 | 91 | bool isPolymerBehavior(DartObject o) => 92 | (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'PolymerBehavior'); 93 | 94 | bool isStoreDef(DartObject o) => (isPolymerElementUri(o.type.element.librarySource.uri)) && (o.type.name == 'StoreDef'); 95 | 96 | bool isInit(DartObject o) => 97 | o != null && (isPolymerElementInitUri(o.type.element.librarySource.uri)) && (o.type.name == 'Init'); 98 | 99 | bool isEntryPoint(DartObject o) => 100 | o != null && (isPolymerElementInitUri(o.type.element.librarySource.uri)) && (o.type.name == 'EntryPoint'); 101 | 102 | bool isInitModule(DartObject o) => 103 | o != null && (isPolymerElementInitUri(o.type.element.librarySource.uri)) && (o.type.name == 'InitModule'); 104 | 105 | bool isHtmlImport(DartObject o) => 106 | o != null && (isPolymerElementHtmlImportUri(o.type.element.librarySource.uri)) && (o.type.name == 'HtmlImport'); 107 | 108 | Iterable allFirstLevelAnnotation(Iterable cus, bool matches(DartObject x)) => 109 | flatten(cus.map((cu) => cu.sortedDirectivesAndDeclarations)) 110 | .map(_element) 111 | .where(notNull) 112 | .map((e) => e.metadata) 113 | .where(notNull) 114 | .map((anno) => getAnnotation(anno, matches)) 115 | .where(notNull); 116 | 117 | typedef bool Matcher(DartObject x); 118 | 119 | X _whichMatcher(DartObject annotation, Map matchers, X orElse) => 120 | matchers.keys.firstWhere((k) => matchers[k](annotation), orElse: () => orElse); 121 | 122 | Map> _collect(Iterable i, {X key(Z z), Y value(Z z)}) { 123 | Map> res = {}; 124 | i.forEach((z) { 125 | X x = key(z); 126 | Y y = value(z); 127 | if (x != null) { 128 | List yy = res.putIfAbsent(x, () => []); 129 | yy.add(y); 130 | } 131 | }); 132 | return res; 133 | } 134 | 135 | Iterable flatten(Iterable> x) => flattenWith(x, (x) => x); 136 | 137 | typedef dynamic FLATTER_WITH_DT(Y); 138 | 139 | Iterable flattenWith(Iterable x, FLATTER_WITH_DT extract) sync* { 140 | for (Y i in x) { 141 | yield* extract(i); 142 | } 143 | } 144 | 145 | class AnnotationInfo { 146 | Element element; 147 | DartObject annotation; 148 | 149 | AnnotationInfo({this.element, this.annotation}); 150 | } 151 | 152 | Map> firstLevelAnnotationMap( 153 | Iterable cus, Map matchers, X orElse) => 154 | _collect( 155 | flatten(flatten(cus.map((cu) => cu.sortedDirectivesAndDeclarations)) 156 | .map(_element) 157 | .where((e) => e?.metadata != null) 158 | .map((e) => e.metadata 159 | .map((a) => a.computeConstantValue()) 160 | .where(notNull) 161 | .map((o) => new AnnotationInfo(element: e, annotation: o)))), 162 | key: (AnnotationInfo o) => _whichMatcher(o.annotation, matchers, orElse), 163 | value: (AnnotationInfo o) => o); 164 | 165 | Element _element(AstNode x) => (x is Declaration) ? x.element : ((x is Directive) ? x.element : null); 166 | 167 | bool hasAnyFirstLevelAnnotation(Iterable cus, bool matches(DartObject x)) => 168 | allFirstLevelAnnotation(cus, matches).isNotEmpty; 169 | 170 | DartObject getAnnotation( 171 | Iterable metadata, // 172 | bool matches(DartObject x)) => 173 | (metadata ?? []).map((an) => an.computeConstantValue()).where(notNull).firstWhere(matches, orElse: () => null); 174 | 175 | bool hasAnnotation( 176 | Iterable metadata, // 177 | bool matches(DartObject x)) => 178 | getAnnotation(metadata, matches) != null; 179 | 180 | ElementAnnotation getElementAnnotation( 181 | Iterable metadata, // 182 | bool matches(DartObject x)) => 183 | metadata.firstWhere((an) => matches(an.computeConstantValue()), orElse: () => null); 184 | 185 | Directory findDartSDKHome() { 186 | if (Platform.environment['DART_HOME'] != null) { 187 | return new Directory(Platform.environment['DART_HOME']); 188 | } 189 | 190 | //print("res:${Platform.resolvedExecutable} exe:${Platform.executable} root:${Platform.packageRoot} cfg:${Platform.packageConfig} "); 191 | // Else tries with current executable 192 | return new File(Platform.resolvedExecutable).parent; 193 | } 194 | 195 | typedef bool matcher(DartObject x); 196 | 197 | matcher anyOf(List matches) => (DartObject o) => matches.any((m) => m(o)); 198 | 199 | bool notNull(x) => x != null; 200 | 201 | bool needsProcessing(LibraryElement le) => hasAnyFirstLevelAnnotation( 202 | le.units.map((u) => u.unit), 203 | anyOf([ 204 | isJsMap, 205 | isBowerImport, 206 | isPolymerRegister, 207 | isInit, 208 | isInitModule, 209 | isHtmlImport, 210 | isPolymerBehavior, 211 | isEntryPoint 212 | ])); 213 | 214 | PropertyInducingElement findField(Element clazz, String name) { 215 | if (clazz == null) { 216 | return null; 217 | } 218 | 219 | if (clazz is ClassElement) { 220 | return clazz.fields.firstWhere((fe) => fe.name == name, 221 | orElse: () => flattenWith(flattenWith(clazz.interfaces ?? [], (InterfaceType x) => x.accessors), 222 | (PropertyAccessorElement ac) => [ac.variable]) 223 | .firstWhere((PropertyInducingElement ac) => ac.name == name, orElse: () { 224 | if (clazz.supertype != clazz) { 225 | return findField(clazz.supertype?.element, name); 226 | } 227 | return null; 228 | })); 229 | } else { 230 | return null; 231 | } 232 | } 233 | 234 | String tsMethodName(String name) { 235 | if (name == 'caller') { 236 | return r"$caller"; 237 | } 238 | return name; 239 | } 240 | 241 | bool isAnonymousConstructor(ConstructorElement c) => (c.name ?? "").isEmpty && !c.isFactory; 242 | 243 | DartType getType(AnalysisContext ctx, String libraryUri, String typeName) => 244 | getLibrary(ctx, libraryUri).getType(typeName).type; 245 | 246 | LibraryElement getLibrary(AnalysisContext ctx, String libraryUri) => 247 | ctx.computeLibraryElement(ctx.sourceFactory.forUri(libraryUri)); 248 | 249 | LibraryElement dartCore(AnalysisContext ctx) => getLibrary(ctx, 'dart:core'); 250 | 251 | // This doesn't work with analizer for me 252 | //typedef X X_FUNCTION(); 253 | //X runWithContext(AnalysisContext ctx, X_FUNCTION body) => runZoned(body, zoneValues: {'dart2ts.analysisContext':ctx}); 254 | X runWithContext(AnalysisContext ctx, Function body) => 255 | runZoned(() => body() as X, zoneValues: {'dart2ts.analysisContext': ctx}); 256 | 257 | AnalysisContext get currentContext => Zone.current['dart2ts.analysisContext']; 258 | -------------------------------------------------------------------------------- /dart2ts/npm.config: -------------------------------------------------------------------------------- 1 | npm config set @dart2ts.packages:registry=http://localhost:4873 2 | npm config set @dart2ts:registry=http://localhost:4873 3 | -------------------------------------------------------------------------------- /dart2ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dart2ts", 3 | "version": "1.0.0", 4 | "description": "js test for dart2ts", 5 | "main": "index.js", 6 | "flat": true, 7 | "directories": { 8 | "doc": "docs", 9 | "lib": "lib", 10 | "test": "test" 11 | }, 12 | "scripts": { 13 | "test": "mocha --exit --recursive test" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/polymer-dart/dart2ts.git" 18 | }, 19 | "author": "", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/polymer-dart/dart2ts/issues" 23 | }, 24 | "homepage": "https://github.com/polymer-dart/dart2ts#readme", 25 | "dependencies": { 26 | "chai": "^4.1.2", 27 | "express": "^4.16.2", 28 | "mocha": "^5.0.1", 29 | "puppeteer": "^1.1.0" 30 | }, 31 | "resolutions": { 32 | "debug": "3.1.0", 33 | "depd": "1.1.2", 34 | "setprototypeof": "1.1.0", 35 | "statuses": "1.4.0", 36 | "mime": "1.6.0", 37 | "mkdirp": "0.5.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dart2ts/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart2ts 2 | author: Vittorio Ballestra 3 | homepage: https://github.com/orgs/polymer-dart 4 | description: A better interface for TS 5 | version: 0.9.15 6 | dependencies: 7 | build: ">=0.11.2" 8 | build_runner: ">=0.6.1" 9 | analyzer: ">=0.30.0 <0.32.0" 10 | args: any 11 | source_gen: any 12 | resource: ">=2.1.2" 13 | yaml: any 14 | executables: 15 | dart2ts: dart2ts 16 | dev_dependencies: 17 | test: any 18 | environment: 19 | sdk: ">=1.8.0 <2.0.0" 20 | -------------------------------------------------------------------------------- /dart2ts/test/e2e_test.dart: -------------------------------------------------------------------------------- 1 | @TestOn('vm') 2 | library my_test; 3 | 4 | import 'package:build_runner/build_runner.dart'; 5 | import 'package:test/test.dart'; 6 | import 'package:dart2ts/dart2ts.dart'; 7 | import 'dart:io'; 8 | import 'package:path/path.dart' as path; 9 | 10 | final String E2E_TEST_PROJECT_PATH = path.canonicalize(path.absolute(path.joinAll(['..', 'e2e_test']))); 11 | 12 | void main() { 13 | group("test test with ${E2E_TEST_PROJECT_PATH}", () { 14 | setUpAll(() async { 15 | print("Build e2e"); 16 | 17 | Directory dartTool = new Directory(path.join(E2E_TEST_PROJECT_PATH, '.dart_tool')); 18 | if (dartTool.existsSync()) { 19 | await dartTool.delete(recursive: true); 20 | } 21 | Config config = new Config(overrides: new IOverrides.parse(''' 22 | ''')); 23 | BuildResult buildResult = await dart2tsBuild(E2E_TEST_PROJECT_PATH, config); 24 | expect(buildResult.status, equals(BuildStatus.success), reason: "Build is ok"); 25 | print("TS Build, now running webpack"); 26 | Process npm = await Process.start('npm', ['run', 'dist'], workingDirectory: E2E_TEST_PROJECT_PATH); 27 | stdout.addStream(npm.stdout); 28 | stderr.addStream(npm.stderr); 29 | int exitCode = await npm.exitCode; 30 | expect(exitCode, equals(0), reason: "Ts Compile Ok"); 31 | }); 32 | 33 | test("execute mocha tests", () async { 34 | Process res = await Process.start('npm', ['run', 'test'], workingDirectory: '.'); 35 | stdout.addStream(res.stdout); 36 | stderr.addStream(res.stderr); 37 | 38 | expect(await res.exitCode, equals(0), reason: "mocha test Ok"); 39 | }, timeout: new Timeout(new Duration(minutes: 5))); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /dart2ts/test/e2e_test.js: -------------------------------------------------------------------------------- 1 | const {expect, assert} = require('chai'); 2 | const puppeteer = require('puppeteer'); 3 | const express = require('express'); 4 | 5 | const expected_logs = [ 6 | 'INDEX> Method Works? or not? - 96', 7 | 'INDEX> Nicky Hayden Lives! Works?, or not?', 8 | 'INDEX> This is a native method, Mario', 9 | 'INDEX> READONLY', 10 | 'INDEX> HI', 11 | 'INDEX> create HI', 12 | 'INDEX>

GOOD MOOOOOOOOOOOOOOOORNING DART2TS!!

', 13 | 'INDEX> Hello Dart2TS', 14 | 'INDEX> DOC! : [object HTMLBodyElement]', 15 | 'INDEX> [ciao],[ciao],[bambina]', 16 | 'INDEX> \n', 17 | 'INDEX> Result 0 : 17 len : 1', 18 | 'INDEX> Result FIRST! : 17', 19 | 'INDEX> wow! Hello world Mario', 20 | 'INDEX> parent :undefined , undefined', 21 | 'INDEX> hi man!', 22 | 'INDEX> once', 23 | 'INDEX> parent :undefined , undefined', 24 | 'INDEX> hi man!', 25 | 'INDEX> twice', 26 | 'INDEX> parent :undefined , undefined', 27 | 'INDEX> hi man!', 28 | 'INDEX> final', 29 | 'INDEX> parent other XXugoxx', 30 | 'INDEX> Yo ugo', 31 | 'INDEX> picio', 32 | 'INDEX> parent other XXciroxx', 33 | 'INDEX> Yo ciro', 34 | 'INDEX> some : oth, x: 5', 35 | 'INDEX> some', 36 | 'INDEX> thing : ops, x: 4', 37 | 'INDEX> thing', 38 | 'INDEX> has : uuu, x: undefined', 39 | 'INDEX> has', 40 | 'INDEX> changed : ops, x: undefined', 41 | 'INDEX> changed', 42 | 'INDEX> A = uga : XXciroxx , undefined', 43 | 'INDEX> U : uga : XXciroxx', 44 | 'INDEX> CHANGED : jungle', 45 | 'INDEX> parent other XXugo2xx', 46 | 'INDEX> Yo ugo2', 47 | 'INDEX> ugo2 says', 48 | 'INDEX> parent other x', 49 | 'INDEX> OPTIND:5', 50 | 'INDEX> parent :withDefault , 42', 51 | 'INDEX> NAMED ON NAMED: withDefault', 52 | 'INDEX> parent :django , 42', 53 | 'INDEX> NAMED ON NAMED: django', 54 | 'INDEX> parent :ciccio , 42', 55 | 'INDEX> NAMED ON NAMED: ciccio', 56 | 'INDEX> bye!', 57 | 'INDEX> start receiving', 58 | 'INDEX> parent :ciao , 0', 59 | 'INDEX> parent :ciao , 1', 60 | 'INDEX> Calling equals == ??', 61 | 'INDEX> Uguali (static typed): true', 62 | 'INDEX> Calling equals == ??', 63 | 'INDEX> Uguali (dynamic typed): true', 64 | 'INDEX> parent :undefined , 15', 65 | 'INDEX> SUM : 15', 66 | 'INDEX> parent :undefined , -5', 67 | 'INDEX> MINUS : -5', 68 | 'INDEX> parent :undefined , -10', 69 | 'INDEX> NEG : -10', 70 | 'INDEX> parent :undefined , 15', 71 | 'INDEX> SUM : 15', 72 | 'INDEX> parent :undefined , -5', 73 | 'INDEX> MINUS : -5', 74 | 'INDEX> parent :undefined , -10', 75 | 'INDEX> NEG : -10', 76 | 'INDEX> HERE : 5', 77 | 'INDEX> -> 5', 78 | 'INDEX> -> 6', 79 | 'INDEX> Duration in minutes : 690, 11:30:00.000000', 80 | 'INDEX> We got [--a--]', 81 | 'INDEX> We got [--b--]', 82 | 'INDEX> Repeat iter', 83 | 'INDEX> Then We got [--a--]', 84 | 'INDEX> Then We got [--b--]', 85 | 'INDEX> I = 0', 86 | 'INDEX> I = 1', 87 | 'INDEX> I = 2', 88 | 'INDEX> I = 3', 89 | 'INDEX> I = 4', 90 | 'INDEX> I = 5', 91 | 'INDEX> I = 6', 92 | 'INDEX> I = 7', 93 | 'INDEX> I = 8', 94 | 'INDEX> I = 9', 95 | 'INDEX> (do) I = 0', 96 | 'INDEX> (do) I = 1', 97 | 'INDEX> (do) I = 2', 98 | 'INDEX> (do) I = 3', 99 | 'INDEX> (do) I = 4', 100 | 'INDEX> (do) I = 5', 101 | 'INDEX> (do) I = 6', 102 | 'INDEX> (do) I = 7', 103 | 'INDEX> (do) I = 8', 104 | 'INDEX> (do) I = 9', 105 | 'INDEX> It\'s CIAO!', 106 | 'INDEX> PI : [3]', 107 | 'INDEX> PI : [1]', 108 | 'INDEX> PI : [4]', 109 | 'INDEX> PI : [1]', 110 | 'INDEX> PI : [5]', 111 | 'INDEX> Received : Event 0', 112 | 'INDEX> Received : Event 1', 113 | 'INDEX> Received : Event 2', 114 | 'INDEX> Received : Event 3', 115 | 'INDEX> Received : Event 4', 116 | 'INDEX> Received : Event 5', 117 | 'INDEX> Received : Event 6', 118 | 'INDEX> Received : Event 7', 119 | 'INDEX> Received : Event 8', 120 | 'INDEX> Received : Event 9', 121 | 'INDEX> CANCEL', 122 | 'INDEX> finished receiving', 123 | 'INDEX> start receiving', 124 | 'INDEX> Received : Event 0', 125 | 'INDEX> Received : Event 1', 126 | 'INDEX> Received : Event 2', 127 | 'INDEX> Received : Event 3', 128 | 'INDEX> Received : Event 4', 129 | 'INDEX> Received : Event 5', 130 | 'INDEX> Received : Event 6', 131 | 'INDEX> Received : Event 7', 132 | 'INDEX> Received : Event 8', 133 | 'INDEX> Received : Event 9', 134 | 'INDEX> finished receiving', 135 | 'INDEX> start receiving', 136 | 'INDEX> Received : Event 0', 137 | 'INDEX> Received : Event 1', 138 | 'INDEX> Received : Event 2', 139 | 'INDEX> Received : Event 3', 140 | 'INDEX> Received : Event 4', 141 | 'INDEX> Received : Event 5', 142 | 'INDEX> Received : Event 6', 143 | 'INDEX> Received : Event 7', 144 | 'INDEX> Received : Event 8', 145 | 'INDEX> Received : Event 9', 146 | 'INDEX> finished receiving', 147 | 'INDEX> start receiving', 148 | 'INDEX> Received : Event 0', 149 | 'INDEX> Received : Event 1', 150 | 'INDEX> Received : Event 2', 151 | 'INDEX> Received : Event 3', 152 | 'INDEX> Received : Event 4', 153 | 'INDEX> Received : Event 5', 154 | 'INDEX> finished receiving', 155 | 'INDEX> start receiving', 156 | 'INDEX> Received : Event 0', 157 | 'INDEX> Received : Event 1', 158 | 'INDEX> Received : Event 2', 159 | 'INDEX> Received : Event 3', 160 | 'INDEX> Received : Event 4', 161 | 'INDEX> Received : Event 5', 162 | 'INDEX> finished receiving', 163 | 'INDEX> Future works', 164 | 'INDEX> Future works2', 165 | 'INDEX> Num 0', 166 | 'INDEX> Num 1', 167 | 'INDEX> Num 2', 168 | 'INDEX> Num 3', 169 | 'INDEX> Num 4' 170 | ]; 171 | 172 | describe('dart2ts', function () { 173 | // Define global variables 174 | let browser; 175 | let page; 176 | let app; 177 | let server; 178 | 179 | before(async function () { 180 | 181 | // Simple server for serving static files 182 | // Simple server for serving static files 183 | app = express(); 184 | app.use(express.static('../e2e_test/dist')); 185 | server = app.listen(9000); 186 | 187 | browser = await puppeteer.launch(); 188 | }); 189 | 190 | after(async function () { 191 | await browser.close(); 192 | await server.close(); 193 | console.log('TEST FINISHED'); 194 | }); 195 | 196 | describe('tests', () => { 197 | before(async () => { 198 | page = await browser.newPage(); 199 | page.on('console', msg => { 200 | for (let i = 0; i < msg.args().length; ++i) 201 | //console.log(`${i}: ${msg.args()[i]}`); 202 | console.log(`TESTS> ${msg.text()}`); 203 | }); 204 | await page.goto('http://localhost:9000/tests.html'); 205 | }); 206 | 207 | after(async () => { 208 | await page.close(); 209 | page = null; 210 | }); 211 | 212 | describe('maps', () => { 213 | it('has maps', async () => { 214 | const testMap = await page.evaluate(() => window.tests.default.test_map.testMap()); 215 | expect(testMap).to.be.equal(3); 216 | 217 | }); 218 | }); 219 | 220 | it('works with redirecting constructors', async () => { 221 | const res = await page.evaluate(() => window.tests.default.test_strange.test1(31516)); 222 | expect(res).to.be.equal(31516); 223 | }); 224 | 225 | it('works with redirecting named constructors with named args', async () => { 226 | const res = await page.evaluate(() => window.tests.default.test_strange.test2(31516)); 227 | expect(res).to.be.equal(31516); 228 | }); 229 | 230 | it('knows how to deal with nulls', async () => { 231 | const reassigned = await page.evaluate(() => window.tests.default.test_strange.test3()); 232 | expect(reassigned).to.equal('value1'); 233 | }); 234 | 235 | it('knows how to deal with null objects', async () => { 236 | const def = await page.evaluate(() => window.tests.default.test_strange.test4(null)); 237 | expect(def).to.equal(-1); 238 | }); 239 | 240 | it('knows how to deal with null objects two times', async () => { 241 | const def = await page.evaluate(() => window.tests.default.test_strange.test5(null)); 242 | expect(def).to.equal(-1); 243 | }); 244 | 245 | it('knows how to deal with null that aren not null', async () => { 246 | const def = await page.evaluate(() => window.tests.default.test_strange.test5('hi')); 247 | expect(def).to.equal(2); 248 | }); 249 | 250 | it('knows how to deal with null objects two times2', async () => { 251 | const def = await page.evaluate(() => window.tests.default.test_strange.test6(null, null)); 252 | expect(def).to.be.null; 253 | }); 254 | 255 | it('knows how to deal with null objects two times3', async () => { 256 | const def = await page.evaluate(() => window.tests.default.test_strange.test7(null, null)); 257 | expect(def).to.be.null; 258 | }); 259 | 260 | it('resolves metadata', async () => { 261 | 262 | const meta = await page.evaluate(() => window.tests.default.testMetadata()); 263 | 264 | expect(meta).to.not.be.null; 265 | expect(meta.annotations).to.deep.equals([{ 266 | "library": "asset:sample_project/lib/test_anno.dart", 267 | "type": "MyAnnotation", 268 | "value": { 269 | "arguments": [ 270 | "Yeah!" 271 | ], 272 | "namedArguments": {} 273 | } 274 | }]); 275 | 276 | 277 | }); 278 | 279 | it('resolves metadata on props too', async () => { 280 | 281 | const meta = await page.evaluate(() => window.tests.default.propAnno()); 282 | 283 | expect(meta).to.not.be.null; 284 | expect(meta).to.deep.equals([{ 285 | "arguments": [ 286 | "onprop" 287 | ], 288 | "namedArguments": {} 289 | }]); 290 | 291 | 292 | }); 293 | 294 | it('async await', async function () { 295 | this.timeout(20000); 296 | 297 | const testAwait = await page.evaluate(() => window.tests.default.testAsync()); 298 | 299 | assert.isArray(testAwait); 300 | expect(testAwait).to.deep.equal([0, 1, 2, 3, 4]); 301 | 302 | }); 303 | 304 | it('works with closures', async () => { 305 | const result = await page.evaluate(() => window.tests.default.test_async_closure.doAsync('Ciao', 'Pippo')); 306 | 307 | expect(result).to.equal("Ciao Pippo"); 308 | }); 309 | 310 | it('works with closures stream', async function () { 311 | this.timeout(3500); 312 | const result = await page.evaluate(() => window.tests.default.test_async_closure.testStream()); 313 | 314 | expect(result).to.equal("Hi Jhon,Hi Jhon,Hi Jhon"); 315 | }); 316 | 317 | it('test cascading', async () => { 318 | const testCascading = await page.evaluate(() => window.tests.default.testCascading()); 319 | 320 | assert.isObject(testCascading); 321 | expect(testCascading.value).equals('ciao'); 322 | expect(testCascading.another.value).equals('Ugo'); 323 | }); 324 | 325 | it('test cascading2', async () => { 326 | const testCascading = await page.evaluate(() => window.tests.default.testCascading().func('c')); 327 | 328 | expect(testCascading).equals('c!'); 329 | }); 330 | 331 | it('test cascading3', async () => { 332 | const testCascading = await page.evaluate(() => { 333 | return window.tests.default.testCascading().func2(); 334 | }); 335 | 336 | expect(testCascading).equals('Hi'); 337 | }); 338 | 339 | it('works with init', async () => { 340 | const r = await page.evaluate(()=> { 341 | return window.tests.default.test_init.properties.x.met(); 342 | }); 343 | 344 | expect(r).to.equal(7); 345 | }); 346 | 347 | it('try_catch', async () => { 348 | const x = await page.evaluate(() => { 349 | return { 350 | t1: window.tests.default.try_catch.doSomethingBad(), 351 | t1f: window.tests.default.try_catch.properties.doSomethingBadFinally, 352 | t2: window.tests.default.try_catch.doSomethingBad('a'), 353 | t2f: window.tests.default.try_catch.properties.doSomethingBadFinally, 354 | t3: window.tests.default.try_catch.doSomethingElseNoCatch(), 355 | t3f: window.tests.default.try_catch.properties.doSomethingElseNoCatchFinally, 356 | t4: window.tests.default.try_catch.doSomethingElseNoCatch('a'), 357 | t4f: window.tests.default.try_catch.properties.doSomethingElseNoCatchFinally 358 | }; 359 | }); 360 | 361 | expect(x.t1).equal('Null string cannot be accessed:'); 362 | expect(x.t1f).equal(1); 363 | expect(x.t2).equal('1'); 364 | expect(x.t2f).equal(2); 365 | expect(x.t3).equal(-2); 366 | expect(x.t3f).equal(1); 367 | expect(x.t4).equal(1); 368 | expect(x.t4f).equal(2); 369 | }); 370 | 371 | it('unicode',async () => { 372 | const prop1 = await page.evaluate(() => { 373 | return window.tests.default.test_unicode.properties.string4 374 | }); 375 | const prop3 = await page.evaluate(() => { 376 | return window.tests.default.test_unicode.properties.string3 377 | }); 378 | 379 | expect(prop1).equal('HH \'h\' mm \'min\' ss \'s\' zzzz'); 380 | expect(prop3).equal('\u09E6'); 381 | 382 | }); 383 | 384 | xit('test js anno', async () => { 385 | const MyClass = await page.evaluate(() => { 386 | return window.tests.default.test_js_anno.MyClass; 387 | }); 388 | 389 | expect(MyClass.otherName).equals('hi'); 390 | }); 391 | 392 | xit('test refs', async () => { 393 | const a1 = await page.evaluate(() => { 394 | return window.tests.default.test_js_anno.testRefs(); 395 | }); 396 | 397 | expect(a1.c).equals(3); 398 | expect(a1.x.c).equals(2); 399 | }); 400 | 401 | }); 402 | 403 | describe('index', () => { 404 | let collected_logs = []; 405 | 406 | before(async () => { 407 | page = await browser.newPage(); 408 | page.on('console', msg => { 409 | 410 | for (let i = 0; i < msg.args().length; ++i) { 411 | //console.log(`${i}: ${msg.args()[i]}`); 412 | if (msg.text().indexOf('[WDS]') >= 0) break; 413 | let m = `INDEX> ${msg.text()}`; 414 | collected_logs.push(m); 415 | //m = m.replace('\'', '\\\'').replace('\n', '\\n'); 416 | //console.log(`'${m}',`); 417 | //console.log(m); 418 | } 419 | }); 420 | await page.goto('http://localhost:9000/index.html'); 421 | }); 422 | 423 | after(async () => { 424 | await page.close(); 425 | page = null; 426 | }); 427 | 428 | it('page should be rendered', async function () { 429 | this.timeout(40000); 430 | 431 | //console.log('waiting for end of work'); 432 | 433 | await page.waitForSelector('div.endofwork', {timeout: 20000}); 434 | 435 | let logs_snapshot = collected_logs.slice(); 436 | expect(logs_snapshot).to.deep.equal(expected_logs); 437 | 438 | const createdTask = await page.evaluate(() => document.querySelector('div.endofwork').textContent); 439 | 440 | // Compare actual text with expected input 441 | //console.log('executing task'); 442 | expect(createdTask).to.equal("finished"); 443 | 444 | await page.screenshot({path: 'test/screens/item.png', fullscreen: true}); 445 | 446 | }); 447 | 448 | }); 449 | 450 | 451 | }); 452 | -------------------------------------------------------------------------------- /docs/NOTES.md: -------------------------------------------------------------------------------- 1 | # STRATEGY 2 | 3 | Different use cases to take into account for designing the translation strategy 4 | 5 | 1. Language constructs : 6 | - Future / Promise 7 | - Iterable / Iterator protocol 8 | - async / async 9 | - sync / function* 10 | - async* / async function* 11 | 12 | ## translating extension methods 13 | 14 | Calling a dart extension method or property on an unknown object cannot be mapped to an extension method reliably. 15 | 16 | The default translation for calling a method or property is to exactly call it 17 | - DART: 18 | ```dart 19 | var x = getSomeX() as dynamic; 20 | print("${x.first}"); // If x is a list it should call extension property first 21 | ``` 22 | - TS (default): 23 | ```typescript 24 | let x = getSomeX(); 25 | core.print(`${x.first}`); 26 | ``` 27 | For this reason we should not use extension methods but instead define `DartArray` that "extends" `Array` and provides the new methods or properties we need. 28 | 29 | How should we treat the following cases: 30 | 1. Dart code that calls a TS library and passes a `DartArray` when it expects an `Array` 31 | 2. Dart code that calls a TS library that returns an `Array` when dart wants a `DartArray` 32 | 3. TS code that calls a Dart library and passes a `Array` when dart wants a `DartArray` 33 | 4. TS code that calls a Dart library that returns a `DartArray` instead of an `Array` 34 | 35 | We have to support thirdy party library that works with `dartdevc` so we cannot restrict by forcing the use of a different class than `List` or leverage the analyzer. 36 | For example this code shoud work 37 | 38 | ```dart 39 | myMethod() { 40 | return new List() as dynamic; 41 | } 42 | 43 | myMethod().add("hi"); 44 | 45 | ``` 46 | 47 | This will be translated as 48 | ```typescript 49 | function myMethod() { 50 | return (any) new Array(); 51 | } 52 | 53 | myMethod().add("hi"); 54 | ``` 55 | 56 | But Ts `Array` doesn't have and `add` method! How does `dartdevc` handle this ? It will translate it with `dsend` that will check dynamically for extension method 57 | otherwise it will call it directly if analyzer could detect it : 58 | ```javascript 59 | 60 | dart.dsend(test.myMethod(), 'add', "hi"); // if myMethod is declared as returning `dynamic` 61 | test.myMethod()[dartx.add]("hi"); // if myMethod is defined as returning `List` 62 | ``` 63 | 64 | `dart.dsend` will check if 'add` corresponds to an extension method ([dartx.add] in this case) and if the actual target has it and then calls it, otherwise it will call `add`. 65 | 66 | Estension method are added to the `Array` prototype thus javascript libraries calling dart will always pass object with extension method enabled. 67 | 68 | There's also an `registerExtension` method that will add the extension to the original prototype. 69 | 70 | 71 | What about using decorators ? 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /e2e_test/.analysis_options: -------------------------------------------------------------------------------- 1 | analyzer: 2 | strong-mode: true 3 | # language: 4 | # enableConditionalDirectives: true 5 | exclude: 6 | - bazel-*/** 7 | - gen/** 8 | -------------------------------------------------------------------------------- /e2e_test/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dart_sdk 3 | dist 4 | -------------------------------------------------------------------------------- /e2e_test/.nvmrc: -------------------------------------------------------------------------------- 1 | v10.10.0 2 | -------------------------------------------------------------------------------- /e2e_test/README.md: -------------------------------------------------------------------------------- 1 | # End to end test project 2 | 3 | ## how to build and run 4 | 5 | 1. dart ../bin/dart2ts build -w 6 | 2. npm run serve 7 | 8 | make changes to the dart sample files and se webpack hotreloading in action!! -------------------------------------------------------------------------------- /e2e_test/dart2ts.dart: -------------------------------------------------------------------------------- 1 | import 'package:build_runner/build_runner.dart'; 2 | import 'package:dart2ts/dart2ts.dart'; 3 | import 'dart:io'; 4 | 5 | main(List args) { 6 | if ((args.length > 0 && args[0] == '-c')) { 7 | Directory dir = new Directory('.dart_tool'); 8 | if (dir.existsSync()) dir.deleteSync(recursive: true); 9 | print("Deleted ${dir.absolute.path}"); 10 | } 11 | 12 | Config config = new Config(overrides: new IOverrides.parse(''' 13 | overrides: 14 | 15 | ''')); 16 | build([ 17 | new BuildAction(new Dart2TsBuilder(), 'sample_project', inputs: ['lib/**.dart']), 18 | ], deleteFilesByDefault: true); 19 | } 20 | -------------------------------------------------------------------------------- /e2e_test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sample 5 | 11 | 12 | 13 | 33 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /e2e_test/lib/.gitignore: -------------------------------------------------------------------------------- 1 | sample*.ts 2 | sample*.js 3 | sample*.js.map 4 | index.js 5 | index.js.map 6 | index.d.ts 7 | function_declaration.ts 8 | list_sample.ts 9 | operand_sample.ts 10 | simple_expression.ts 11 | class_constructors.ts 12 | strange_prefix_case.ts 13 | extending_list.ts 14 | array_from.ts 15 | expando.ts 16 | field_array.ts 17 | test_stream.ts 18 | method_ref.ts 19 | mini_html.ts 20 | try_catch.ts 21 | *.js 22 | *.js.map 23 | *.d.ts 24 | test_*.ts 25 | assign_op.ts 26 | async_methods.ts 27 | catch_with_stack.ts 28 | enum.ts 29 | initializers.ts 30 | mixin.ts 31 | nativewrapper.ts 32 | -------------------------------------------------------------------------------- /e2e_test/lib/array_from.dart: -------------------------------------------------------------------------------- 1 | void doSomething() { 2 | List str = new List.from((() sync* { 3 | yield "Hello"; 4 | yield "world"; 5 | })()); 6 | 7 | print("Strings : ${str}"); 8 | } 9 | -------------------------------------------------------------------------------- /e2e_test/lib/assign_op.dart: -------------------------------------------------------------------------------- 1 | doSomething() { 2 | num a; 3 | a=20; 4 | a+=5; 5 | a-=5; 6 | a*=10; 7 | a/=10; 8 | } -------------------------------------------------------------------------------- /e2e_test/lib/async_methods.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | class AsyncMethods { 4 | Future delayedString(String arg) async { 5 | await new Future.delayed(new Duration(seconds: 1)); 6 | return arg; 7 | } 8 | 9 | static delayedStaticString(String arg) async { 10 | await new Future.delayed(new Duration(seconds: 1)); 11 | return arg; 12 | } 13 | 14 | delayedStream(int n, String arg) async* { 15 | for (int i = 0; i < n; i++) { 16 | String res = await delayedString(arg); 17 | yield res; 18 | } 19 | } 20 | 21 | static delayedStaticStream(int n, String arg) async* { 22 | for (int i = 0; i < n; i++) { 23 | String res = await delayedStaticString(arg); 24 | yield res; 25 | } 26 | } 27 | 28 | // And generators too 29 | generator(int n, String arg) sync* { 30 | for (int i = 0; i < n; i++) { 31 | yield arg; 32 | } 33 | } 34 | 35 | static staticGenerator(int n, String arg) sync* { 36 | for (int i = 0; i < n; i++) { 37 | yield arg; 38 | } 39 | } 40 | } 41 | 42 | generatorFunction(int n, String arg) sync* { 43 | for (int i = 0; i < n; i++) { 44 | yield arg; 45 | } 46 | } 47 | 48 | delayedStreamFunction(int n, String arg) async* { 49 | for (int i = 0; i < n; i++) { 50 | String res = await delayedStringFunction(arg); 51 | yield res; 52 | } 53 | } 54 | 55 | delayedStringFunction(String arg) async { 56 | await new Future.delayed(new Duration(seconds: 1)); 57 | return arg; 58 | } 59 | 60 | useThat(String seed) async { 61 | AsyncMethods asyncMethods = new AsyncMethods(); 62 | for (String cuc in generatorFunction(5, seed)) { 63 | await for (String ciup in delayedStreamFunction(5, cuc)) { 64 | for (String str in AsyncMethods.staticGenerator(5, ciup)) { 65 | for (String cip in asyncMethods.generator(5, str)) { 66 | await for (String pip in AsyncMethods.delayedStaticStream(5, cip)) { 67 | await for (String tri in asyncMethods.delayedStream(5, pip)) { 68 | print("Result static: ${await AsyncMethods.delayedStaticString(tri)}"); 69 | print("Result : ${await asyncMethods.delayedString(tri)}"); 70 | print("Result func: ${await delayedStringFunction(tri)}"); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /e2e_test/lib/catch_with_stack.dart: -------------------------------------------------------------------------------- 1 | doSomething() { 2 | try { 3 | throw "error"; 4 | } catch (error, stack) { 5 | print("ERORR:${error}, stack:${stack}"); 6 | } 7 | } -------------------------------------------------------------------------------- /e2e_test/lib/class_constructors.dart: -------------------------------------------------------------------------------- 1 | import 'function_declaration.dart' as func; 2 | 3 | class SomeClass { 4 | String name; 5 | int ord = 4; 6 | String message = "no msg"; 7 | 8 | SomeClass(this.name, {this.ord}) { 9 | message = "Ciao ${name} [${ord}]"; 10 | } 11 | 12 | SomeClass.withName(String name, {int ord1}) : this(name, ord: 5 + ord1); 13 | 14 | SomeClass.withOrg(int ord) : this.withName('org'); 15 | 16 | factory SomeClass.noRemorse() => new SomeClass.withName("No repent"); 17 | } 18 | 19 | class DerivedClass extends SomeClass { 20 | DerivedClass() : super.withName('pippo', ord1: 100); 21 | 22 | DerivedClass.withName() : super.withOrg(1000) { 23 | message = "Overridden"; 24 | } 25 | } 26 | 27 | class Derived1 extends SomeClass { 28 | factory Derived1() { 29 | return new Derived1._(); 30 | } 31 | 32 | Derived1._() : super('der1'); 33 | } 34 | 35 | class Derived2 extends Derived1 { 36 | factory Derived2() { 37 | return new Derived2._(); 38 | } 39 | 40 | Derived2._() : super._(); 41 | } 42 | 43 | class Generic1 extends SomeClass { 44 | X x1; 45 | factory Generic1(X x1) { 46 | return new Generic1.named(x1); 47 | } 48 | 49 | Generic1.named(this.x1) : super.withOrg(10); 50 | 51 | factory Generic1.named2(X x2) { 52 | return new Generic1.named(x2); 53 | } 54 | 55 | factory Generic1.named3(X x3) { 56 | return new Generic1(x3); 57 | } 58 | } 59 | 60 | void useEm() { 61 | SomeClass x = new SomeClass('hi', ord: 5); 62 | 63 | SomeClass y = new SomeClass.withName('bye'); 64 | 65 | SomeClass z = new SomeClass.withOrg(5); 66 | 67 | SomeClass w = new SomeClass.noRemorse(); 68 | 69 | Derived1 d1 = new Derived1(); 70 | 71 | Derived2 d2 = new Derived2(); 72 | 73 | Generic1 g1 = new Generic1(true); 74 | 75 | Generic1 g2 = new Generic1.named3('hello'); 76 | 77 | List abcd = [x, y, z, w, d1, d2]; 78 | } 79 | 80 | void useTopFromAnother() { 81 | func.topLevelSetter = useEm; 82 | 83 | func.topLevelVar = useEm; 84 | 85 | func.topLevelVar(); 86 | 87 | func.topLevelSetter(); 88 | 89 | print("F1 :${func.topLevelSetter}, F2: ${func.topLevelVar}"); 90 | } 91 | -------------------------------------------------------------------------------- /e2e_test/lib/enum.dart: -------------------------------------------------------------------------------- 1 | enum Fruits { 2 | APPLE, 3 | PEAR, 4 | MANDARINO, 5 | MANDORLA 6 | } -------------------------------------------------------------------------------- /e2e_test/lib/expando.dart: -------------------------------------------------------------------------------- 1 | class MyClass { 2 | 3 | } 4 | 5 | class MyOtherClass { 6 | 7 | } 8 | 9 | 10 | void doSomethingWith() { 11 | 12 | Expando exp = new Expando(); 13 | 14 | MyOtherClass other = new MyOtherClass(); 15 | 16 | exp[other] = new MyClass(); 17 | 18 | MyClass val = exp[other]; 19 | 20 | } -------------------------------------------------------------------------------- /e2e_test/lib/exports.ts: -------------------------------------------------------------------------------- 1 | import * as s1 from './sample1'; 2 | import * as t1 from './test_cascading'; 3 | import * as t2 from './test_js_anno'; 4 | import * as t3 from './test_anno'; 5 | import * as test_map$ from './test_map'; 6 | import * as test_strange from './test_strange'; 7 | import * as test_async_closure from './test_async_closure'; 8 | import * as try_catch from './try_catch'; 9 | import * as test_unicode from './test_unicodeEscape'; 10 | import * as test_init from './test_initializers'; 11 | 12 | export default { 13 | testAsync: s1.testAsync, 14 | testCascading: t1.testCascading, 15 | test_js_anno: t2, 16 | testMetadata: t3.testMetadata, 17 | propAnno: t3.propAnno, 18 | test_map: test_map$, 19 | test_strange: test_strange, 20 | test_async_closure: test_async_closure, 21 | try_catch: try_catch, 22 | test_unicode: test_unicode, 23 | test_init : test_init 24 | } 25 | -------------------------------------------------------------------------------- /e2e_test/lib/extending_list.dart: -------------------------------------------------------------------------------- 1 | import 'dart:collection'; 2 | 3 | /** 4 | * TODO : Investigate Change operator "[]" overriding implementation using ES6 proxies. 5 | * This will allow the use of List and Maps with operator "[]” in a seamless way. 6 | * 7 | * Otherwise: we have to take into account dart annotations as well as ovverides.yml when choosing the 8 | * operator translation. 9 | * 10 | * TODO: Fix the logic that does class overrides to stop at the first class 11 | * 12 | */ 13 | 14 | /** 15 | * Extending iterable test 16 | */ 17 | 18 | class MyIterable extends Iterable { 19 | X _x; 20 | 21 | MyIterable(this._x); 22 | 23 | @override 24 | Iterator get iterator => new MyIterator(_x); 25 | } 26 | 27 | class MyIterator extends Iterator { 28 | X _x; 29 | int _count; 30 | 31 | MyIterator(this._x) : _count = 0; 32 | 33 | @override 34 | X get current => _x; 35 | 36 | @override 37 | bool moveNext() { 38 | return _count++ < 10; 39 | } 40 | } 41 | 42 | /** 43 | * Extending the list with ListBase 44 | */ 45 | class MyList extends ListBase { 46 | X _x; 47 | 48 | MyList(this._x); 49 | 50 | @override 51 | int get length => 10; 52 | 53 | set length(int l) {} 54 | 55 | 56 | X operator [](int index) { 57 | return _x; 58 | } 59 | 60 | operator []=(int index, X value) {} 61 | } 62 | 63 | /** 64 | * Extending the list with the mixin 65 | */ 66 | 67 | class MyList2 extends ListMixin implements List { 68 | @override 69 | int get length => this._list.length; 70 | 71 | set length(int l) => this._list.length = l; 72 | 73 | List _list; 74 | 75 | MyList2(this._list):super(); 76 | 77 | 78 | X operator [](int index) => _list[index]; 79 | 80 | operator []=(int index, X value) { 81 | _list[index] = value; 82 | } 83 | } 84 | 85 | /** This things should work */ 86 | 87 | // Iterate in the usual way 88 | String test1() { 89 | MyIterable it = new MyIterable("Valentino"); 90 | String res = ""; 91 | for (String x in it) { 92 | res = "${res},${x}"; 93 | } 94 | return res; 95 | } 96 | 97 | String test2() { 98 | return new MyIterable("Mario").join(','); 99 | } 100 | 101 | String test3() { 102 | return new MyList("Giovanni").join(','); 103 | } 104 | 105 | String test4() { 106 | Iterable it = new MyList("Giacomo"); 107 | String res = ""; 108 | for (String x in it) { 109 | res = "${res},${x}"; 110 | } 111 | return res; 112 | } 113 | 114 | String test5() { 115 | Iterator i = new MyList("Luigi").iterator; 116 | String res = ""; 117 | while (i.moveNext()) { 118 | res = "${res},${i.current}"; 119 | } 120 | return res; 121 | } 122 | 123 | String test6() { 124 | return new MyList2(new MyList("Leonardo")).join(','); 125 | } 126 | 127 | String test7() { 128 | Iterable it = new MyList2(new MyList("Alfredo")); 129 | String res = ""; 130 | for (String x in it) { 131 | res = "${res},${x}"; 132 | } 133 | return res; 134 | } 135 | 136 | String test8() { 137 | Iterator i = new MyList2(new MyList("Alberto")).iterator; 138 | String res = ""; 139 | while (i.moveNext()) { 140 | res = "${res},${i.current}"; 141 | } 142 | return res; 143 | } 144 | -------------------------------------------------------------------------------- /e2e_test/lib/field_array.dart: -------------------------------------------------------------------------------- 1 | class TestClass { 2 | List children = []; 3 | 4 | void doSomething() { 5 | TestClass t = new TestClass(); 6 | children.add(t); 7 | children.remove(t); 8 | } 9 | } -------------------------------------------------------------------------------- /e2e_test/lib/function_declaration.dart: -------------------------------------------------------------------------------- 1 | bool boolFunction(int arg) { 2 | return null; 3 | } 4 | 5 | int intFunction(int arg, [int opt, int opt2 = 4]) { 6 | return 5; 7 | } 8 | 9 | String stringFunction(int arg, {int named, int named2: 4}) { 10 | return "Hello Jhonny!"; 11 | } 12 | 13 | varFunction(String nornalArg, [int optionalArg]) { 14 | return null; 15 | } 16 | 17 | void voidFunction(normalArg, {String namedArgument}) {} 18 | 19 | List genericFunction() { 20 | return null; 21 | } 22 | 23 | set topLevelSetter(Function f) {} 24 | 25 | Function get topLevelSetter => null; 26 | 27 | Function topLevelVar; 28 | 29 | String topLevelWithInit = "ciao ${topLevelVar()}"; 30 | 31 | functionInsideFunctions() { 32 | insideIt(x) { 33 | return 10; 34 | } 35 | 36 | Function anotherFunc = (y) { 37 | return y + 1; 38 | }; 39 | 40 | var anotherFunc2; 41 | 42 | anotherFunc2 = () => "hi"; 43 | 44 | topLevelSetter = () => "bad"; 45 | 46 | topLevelVar = () => "TOP"; 47 | 48 | print('${topLevelSetter}'); 49 | 50 | var someClosure = (x) => 10; 51 | 52 | return insideIt; 53 | } 54 | -------------------------------------------------------------------------------- /e2e_test/lib/index.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart2ts/annotations.dart'; 2 | import 'sample1.dart'; 3 | 4 | @onModuleLoad 5 | void index() { 6 | main(['ciao','ciao','bambina']); 7 | } -------------------------------------------------------------------------------- /e2e_test/lib/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sample 5 | 11 | 12 | 13 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /e2e_test/lib/index.ts: -------------------------------------------------------------------------------- 1 | /** Library asset:sample_project/lib/index.dart */ 2 | import {is,isNot,equals} from "@dart2ts/dart/_common"; 3 | import {defaultConstructor,namedConstructor,namedFactory,defaultFactory,DartClass,Implements,With,op,Op,OperatorMethods,DartClassAnnotation,DartMethodAnnotation,DartPropertyAnnotation,Abstract,AbstractProperty,int,bool,double,Omit} from "@dart2ts/dart/utils"; 4 | import * as _common from "@dart2ts/dart/_common"; 5 | import * as core from "@dart2ts/dart/core"; 6 | import * as async from "@dart2ts/dart/async"; 7 | import * as lib3 from "./sample1"; 8 | 9 | export var index : () => void = () : void => { 10 | lib3.main(new core.DartList.literal('ciao','ciao','bambina')); 11 | }; 12 | export class properties { 13 | } 14 | // On module load 15 | 16 | index(); 17 | -------------------------------------------------------------------------------- /e2e_test/lib/initializers.dart: -------------------------------------------------------------------------------- 1 | class WithInit { 2 | static const String CONST="ciao"; 3 | String field1= "ciao"; 4 | int field2 = 2; 5 | 6 | WithInit(); 7 | 8 | WithInit.named(this.field2,{this.field1}) { 9 | 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /e2e_test/lib/list_sample.dart: -------------------------------------------------------------------------------- 1 | import 'function_declaration.dart'; 2 | 3 | bool doSomethingWithLists() { 4 | List list = [ 5 | "one", 6 | "two", 7 | "three", 8 | "four", 9 | ]; 10 | 11 | 12 | var e = list.map((s)=> "Value ${s}"); 13 | 14 | List anotherList = e.toList(); 15 | 16 | print("First ${anotherList.first} , ${anotherList.last} : ${anotherList.sublist(2,3).first}"); 17 | 18 | var x; 19 | 20 | x = anotherList; 21 | 22 | print("First ${x.first} , ${x.last} : ${x.sublist(2,3).first}"); 23 | 24 | 25 | return true; 26 | } 27 | 28 | 29 | 30 | void useTopFromAnother() { 31 | topLevelSetter=doSomethingWithLists; 32 | 33 | topLevelVar = doSomethingWithLists; 34 | 35 | topLevelVar(); 36 | 37 | topLevelSetter(); 38 | 39 | print("F1 :${topLevelSetter}, F2: ${topLevelVar}"); 40 | } -------------------------------------------------------------------------------- /e2e_test/lib/method_ref.dart: -------------------------------------------------------------------------------- 1 | class MyClass { 2 | int _num; 3 | 4 | String Function(String x, String y) _handler; 5 | 6 | MyClass(this._num, [String Function(String x, String y) h]) { 7 | testCallingNamed(handler: h ?? _aMethod); 8 | 9 | callingStatic(_aMethod); 10 | } 11 | 12 | String _aMethod(String x, String y) { 13 | return "Method ${x} ${y} - ${_num}"; 14 | } 15 | 16 | void testCallingNamed({String Function(String x, String y) handler}) { 17 | _handler = handler; 18 | } 19 | 20 | static callingStatic({String Function(String x, String y) handler}) {} 21 | 22 | String doSomethingWith(String Function(String x, String y) proc, String x) => proc(x, ' or not?'); 23 | 24 | void testMethodRef() { 25 | print(doSomethingWith(_handler, 'Works?')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /e2e_test/lib/mini_html.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library mini_html; 3 | 4 | import 'package:js/js.dart'; 5 | 6 | @JS('window') 7 | external Window get window; 8 | 9 | @JS('document') 10 | external Document get document; 11 | 12 | @JS("Window") 13 | abstract class Window { 14 | external void alert(String msg); 15 | external void scroll(num x,num y); 16 | } 17 | 18 | @JS("Element") 19 | abstract class Element implements Node {} 20 | 21 | @JS("HTMLElement") 22 | abstract class HTMLElement implements Element {} 23 | 24 | @JS("Node") 25 | abstract class Node { 26 | external appendChild(Node node); 27 | } 28 | 29 | @JS("Document") 30 | abstract class Document { 31 | external HTMLElement createElement(String tagName); 32 | } 33 | 34 | HTMLElement createDiv() => document.createElement('div'); -------------------------------------------------------------------------------- /e2e_test/lib/mixin.dart: -------------------------------------------------------------------------------- 1 | class Mixin { 2 | String sayHello(String to) => "Hello ${to}!"; 3 | } 4 | 5 | class MyClass extends Object with Mixin { 6 | selfHello() { 7 | sayHello("Me"); 8 | } 9 | } 10 | 11 | class AnotherClass extends MyClass with Mixin { 12 | String sayHello(String to) => "Ciao ${to}"; 13 | selfHello() { 14 | sayHello("Me"); 15 | } 16 | } -------------------------------------------------------------------------------- /e2e_test/lib/nativewrapper.dart: -------------------------------------------------------------------------------- 1 | doSomething() { 2 | int x = 5; 3 | int y = x.abs(); 4 | 5 | String str = "ciao"; 6 | int z = str.codeUnitAt(1); 7 | 8 | double w = 5.5.floorToDouble(); 9 | 10 | String rev = "ciao".toUpperCase(); 11 | 12 | List codes = rev.codeUnits; 13 | 14 | // Some static methods : 15 | 16 | int n = int.parse("5"); 17 | double d = double.parse("5.4"); 18 | num N = num.parse("3.14"); 19 | } 20 | -------------------------------------------------------------------------------- /e2e_test/lib/operand_sample.dart: -------------------------------------------------------------------------------- 1 | class WithOperand { 2 | operator+(WithOperand another) { 3 | return new WithOperand(); 4 | } 5 | } 6 | 7 | class SubClass extends WithOperand { 8 | 9 | } 10 | 11 | doSomeOps() { 12 | WithOperand a = new WithOperand(),b = new WithOperand(); 13 | 14 | WithOperand c = a + b; 15 | 16 | int d = 5, e = 5; 17 | int f = d + e; 18 | 19 | return new SubClass() + new SubClass(); 20 | } -------------------------------------------------------------------------------- /e2e_test/lib/sample1.dart: -------------------------------------------------------------------------------- 1 | import 'sample2.dart' as xy; 2 | import 'package:js/js.dart'; 3 | import 'sample3.dart'; 4 | import 'sample4.dart'; 5 | import 'sample5.dart'; 6 | import 'package:dart2ts/annotations.dart'; 7 | import 'test_stream.dart' show testDaStream; 8 | import 'method_ref.dart' as mref show MyClass; 9 | import 'dart:async'; 10 | 11 | part 'test_async.dart'; 12 | 13 | @TS(stringInterpolation: true) 14 | HTMLDivElement testInterpolate(String _, {List literals, List values}) { 15 | if (_ != null) { 16 | throw "String interpolation called directly"; 17 | } 18 | HTMLDivElement div = document.createElement('div'); 19 | int i; 20 | for (i = 0; i < literals.length; i++) { 21 | String prefix = literals[i]; 22 | div.appendChild(document.createElement('span')..innerHTML = prefix); 23 | if (i < values.length) { 24 | var obj = values[i]; 25 | if (obj is Element) { 26 | div.appendChild(obj); 27 | } else { 28 | div.appendChild(document.createElement('span')..innerHTML = ("${obj}")); 29 | } 30 | } 31 | } 32 | return div; 33 | } 34 | 35 | void main(List args) { 36 | new mref.MyClass(96).testMethodRef(); 37 | new mref.MyClass(69, (a, b) => 'Nicky Hayden Lives! ${a}, ${b}').testMethodRef(); 38 | 39 | pippo(String x) => testInterpolate("[${x}]"); 40 | document.body.appendChild(testInterpolate("Ciao ${args[0]} e ${args[1]}. E ora : ${pippo(args[2])}")); 41 | 42 | // Should become : 43 | // testInterpolate(literals:['Ciao ',' e '],values:[args[0],args[1]]) 44 | 45 | NativeClass nativeClass = new NativeClass(); 46 | printToBody(nativeClass.doSomething('Mario')); 47 | printToBody(nativeClass.readOnlyString); 48 | nativeClass.normal = "HI"; 49 | printToBody(nativeClass.normal); 50 | printToBody(nativeClass.create()); 51 | 52 | printToBody("

GOOD MOOOOOOOOOOOOOOOORNING DART2TS!!

"); 53 | xy.sayHello('Hello Dart2TS'); 54 | 55 | printToBody("DOC! : ${document.body}"); 56 | 57 | HTMLDivElement e = (document.createElement('div')..innerHTML = 'ciao ciao dart 2ts!!') as HTMLDivElement; 58 | document.body.appendChild(e); 59 | 60 | ciao(String x) { 61 | xy.sayHello(x); 62 | } 63 | 64 | printToBody(args.map((x) => "[${x}]").join(',')); 65 | printToBody('\n'); 66 | 67 | int P = [0].first; 68 | int n = 5; 69 | n = ((n + 4) * 2) ^ 3; 70 | List values = [n]; 71 | 72 | printToBody("Result ${P} : ${values[0]} len : ${values.length}"); 73 | 74 | int x = [0].first + (values).first; 75 | 76 | printToBody("Result FIRST! : ${values.first}"); 77 | 78 | String c = "wow!"; 79 | 80 | ciao(((String x) => (String y) { 81 | return (z) => "${c} $x $y $z"; 82 | })('Hello')('world')('Mario')); 83 | 84 | new xy.MySampleClass1().sayIt('once'); 85 | 86 | xy.MySampleClass1 other = new xy.MySampleClass1(); 87 | other.sayIt2('twice'); 88 | 89 | xy.createSampleClass1().sayIt('final'); 90 | 91 | xy.createSampleClass2('ugo').sayIt2('picio', 5); 92 | 93 | xy.MySampleClass1 a = xy.createSampleClass2('ciro') 94 | ..sayItWithNamed('some', x: 5, other: 'oth') 95 | ..sayItWithNamed('thing', x: 4) 96 | ..sayItWithNamed('has', other: 'uuu') 97 | ..sayItWithNamed('changed'); 98 | 99 | printToBody("A = ${a.title} , ${a.otherField}"); 100 | 101 | a.otherField = a; 102 | 103 | printToBody("U : ${a.otherField.otherField.title}"); 104 | 105 | a.theTitle = 'jungle'; 106 | printToBody("CHANGED : ${a.title}"); 107 | 108 | new xy.MySampleClass1.another('ugo2').sayIt('ugo2 says'); 109 | 110 | new xy.MySampleClass2(); 111 | 112 | new xy.MySampleClass2.extra(); 113 | 114 | new xy.MySampleClass2.extra(namedOnNamed: (1 == 1) ? 'django' : 'tango'); 115 | 116 | new xy.MakeItReal(); 117 | 118 | printToBody('bye!'); 119 | 120 | testDaStream().then((_) { 121 | testFuture().then((_) { 122 | printToBody("Future works"); 123 | testFuture2(); 124 | }); 125 | }); 126 | 127 | //printToBody('LIB: ${getMetadata(xy.MySampleClass1).library}'); 128 | 129 | xy.AnotherClass a0 = new xy.AnotherClass(named: 'ciao',num: 0)..count = 5; 130 | xy.AnotherClass a1 = new xy.AnotherClass(named: 'ciao',num: 1)..count = 10; 131 | printToBody('Uguali (static typed): ${a0 == a1}'); 132 | printToBody('Uguali (dynamic typed): ${(a0 as dynamic) == (a1 as dynamic)}'); 133 | 134 | printToBody('SUM : ${(a0 + a1).count}'); 135 | printToBody('MINUS : ${(a0 - a1).count}'); 136 | printToBody('NEG : ${(-a1).count}'); 137 | 138 | var x0 = a0 as dynamic; 139 | var x1 = a1 as dynamic; 140 | 141 | printToBody('SUM : ${(x0 + x1).count}'); 142 | printToBody('MINUS : ${(x0 - x1).count}'); 143 | printToBody('NEG : ${(-x1).count}'); 144 | 145 | printToBody(('HERE : ${a0.testClosure()}')); 146 | 147 | a0.testMethodIterator().map((i) => "-> ${i}").forEach((s) => printToBody(s)); 148 | 149 | Duration d1 = new Duration(hours: 10); 150 | Duration d2 = new Duration(hours: 1, minutes: 30); 151 | 152 | Duration d3 = d1 + d2; 153 | 154 | printToBody("Duration in minutes : ${d3.inMinutes}, ${d3.toString()}"); 155 | 156 | // Check for iterable 157 | Iterable xx = ['a', 'b'].map((x) => "--${x}--").map((x) => "[${x}]"); 158 | for (String x in xx) { 159 | printToBody('We got ${x}'); 160 | } 161 | 162 | printToBody('Repeat iter'); 163 | for (String x in xx) { 164 | printToBody('Then We got ${x}'); 165 | } 166 | 167 | // WHLE 168 | int i = 0; 169 | while (i < 10) { 170 | printToBody('I = ${i}'); 171 | i++; 172 | } 173 | 174 | // DO 175 | i = 0; 176 | do { 177 | printToBody('(do) I = ${i}'); 178 | i++; 179 | } while (i < 10); 180 | 181 | // Switch; 182 | String cond = 'ciao'; 183 | switch (cond) { 184 | case 'pippo': 185 | printToBody('It is PIPPO!'); 186 | break; 187 | case 'ciao': 188 | printToBody('It\'s CIAO!'); 189 | break; 190 | default: 191 | printToBody('It is FLANAGAN!'); 192 | } 193 | 194 | var litMap = {'ciccio': 5, 'pluto': 10}; 195 | 196 | // Generator 197 | for (String pippo in (() sync* { 198 | yield 3; 199 | yield 1; 200 | yield 4; 201 | yield 1; 202 | yield 5; 203 | })() 204 | .map((n) => "[${n}]")) { 205 | printToBody("PI : ${pippo}"); 206 | } 207 | } 208 | 209 | testFuture2() async { 210 | await testFuture(); 211 | printToBody('Future works2'); 212 | await cips(); 213 | 214 | // Signal end of work 215 | document.body.appendChild(document.createElement('div')..innerHTML = '
finished
'); 216 | } 217 | -------------------------------------------------------------------------------- /e2e_test/lib/sample2.dart: -------------------------------------------------------------------------------- 1 | void sayHello(String msg) { 2 | print(msg); /* */ 3 | } 4 | 5 | class AnotherClass { 6 | String _title; 7 | 8 | String get title => _title; 9 | 10 | num count = 0; 11 | 12 | void set theTitle(String t) => _title = t; 13 | 14 | AnotherClass otherField; 15 | 16 | AnotherClass({String named, int num}) { 17 | print('parent :${named} , ${num}'); 18 | count = num; 19 | this._title = ''; 20 | } 21 | 22 | AnotherClass.other(String x) { 23 | print('parent other ${x}'); 24 | this._title = 'uga : ${x}'; 25 | } 26 | 27 | operator ==(var other) { 28 | print('Calling equals ${this._title} == ${(other as AnotherClass)._title} ??'); 29 | return this._title == (other as AnotherClass)._title; 30 | } 31 | 32 | AnotherClass operator +(AnotherClass other) { 33 | return new AnotherClass(num: this.count + other.count); 34 | } 35 | 36 | AnotherClass operator -() { 37 | return new AnotherClass(num: -this.count); 38 | } 39 | 40 | AnotherClass operator -(AnotherClass other) { 41 | return new AnotherClass(num: this.count - other.count); 42 | } 43 | 44 | int testClosure() { 45 | here() { 46 | return this.count; 47 | } 48 | 49 | return here(); 50 | } 51 | 52 | Iterable testMethodIterator() => (() sync* { 53 | yield count++; 54 | yield count++; 55 | })(); 56 | } 57 | 58 | class MySampleClass1 extends AnotherClass { 59 | MySampleClass1() : super() { 60 | print('hi man!'); 61 | } 62 | 63 | MySampleClass1.another(String who) : super.other('XX${who}xx') { 64 | print('Yo ${who}'); 65 | } 66 | 67 | void sayIt(String msg) => sayHello(msg); 68 | 69 | void sayIt2(String msg, [num pippo = -1]) { 70 | sayHello(msg); 71 | } 72 | 73 | void sayItWithNamed(String arg, {String other: 'ops', int x}) { 74 | print("${arg} : ${other}, x: ${x}"); 75 | sayIt2(arg); 76 | } 77 | } 78 | 79 | class MySampleClass2 extends AnotherClass { 80 | MySampleClass2([int optInd = 5]) : super.other('x') { 81 | print("OPTIND:${optInd}"); 82 | } 83 | 84 | MySampleClass2.extra({String namedOnNamed: 'withDefault'}) : super(named: namedOnNamed, num: 42) { 85 | print("NAMED ON NAMED: ${namedOnNamed}"); 86 | } 87 | } 88 | 89 | class MakeItReal extends MySampleClass2 { 90 | MakeItReal() : super.extra(namedOnNamed: 'ciccio') {} 91 | } 92 | 93 | MySampleClass1 createSampleClass1() => new MySampleClass1(); 94 | 95 | MySampleClass1 createSampleClass2(String x) => new MySampleClass1.another(x); 96 | -------------------------------------------------------------------------------- /e2e_test/lib/sample3.dart: -------------------------------------------------------------------------------- 1 | import 'package:js/js.dart'; 2 | 3 | @JS() 4 | external void alert(String); 5 | 6 | @JS() 7 | class Document { 8 | external Element get body; 9 | 10 | external Element createElement(String div); 11 | } 12 | 13 | @JS() 14 | external Document get document; 15 | 16 | @JS() 17 | class Element { 18 | String innerHTML; 19 | 20 | external void appendChild(Element e); 21 | } 22 | 23 | @JS() 24 | class HTMLDivElement extends Element {} 25 | 26 | @JS() 27 | class HTMLSpanElement extends Element {} 28 | 29 | void printToBody(String message) { 30 | print(message); 31 | document.body.appendChild(document.createElement('div')..innerHTML = message); 32 | } 33 | -------------------------------------------------------------------------------- /e2e_test/lib/sample4.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'sample3.dart'; 3 | 4 | Future testFuture() async { 5 | await simpleAsyncFunc(); 6 | } 7 | 8 | Future simpleAsyncFunc() async { 9 | await new Future.delayed(new Duration(seconds: 1)); 10 | return true; 11 | } 12 | 13 | Stream simpleAsyncStreamFunc() async* { 14 | for (int i = 0; i < 5; i++) { 15 | await new Future.delayed(new Duration(milliseconds: 500)); 16 | yield i; 17 | } 18 | } 19 | 20 | Future cips() async { 21 | await for (String x in simpleAsyncStreamFunc().map((x) => 'Num ${x}')) { 22 | printToBody(x); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /e2e_test/lib/sample5.dart: -------------------------------------------------------------------------------- 1 | @JS('NativeNamespace') 2 | library myNativeNamespace; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:dart2ts/annotations.dart'; 6 | 7 | @JS('NativeClass') 8 | @TS(generate: true) 9 | class NativeClass { 10 | external String get readOnlyString; 11 | 12 | external String get normal; 13 | 14 | external void set normal(String); 15 | 16 | external String doSomething(String name); 17 | 18 | external T create(); 19 | } 20 | -------------------------------------------------------------------------------- /e2e_test/lib/sample_var.dart: -------------------------------------------------------------------------------- 1 | 2 | class Sample { 3 | String field; 4 | } 5 | 6 | sampleWithVar() { 7 | Sample a = new Sample(); 8 | 9 | a.field= "Ciao"; 10 | } -------------------------------------------------------------------------------- /e2e_test/lib/simple_expression.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as m; 2 | 3 | class SomeClass { 4 | SomeClass parent; 5 | String field; 6 | String get otherField => "pippo"; 7 | void set otherField(String value) {} 8 | 9 | implicitThis(String val) { 10 | String prev = field + otherField; 11 | field=val; 12 | otherField = val; 13 | 14 | 15 | return prev; 16 | } 17 | } 18 | 19 | class Derived extends SomeClass { 20 | implicitThis2(String val) { 21 | String prev = field + otherField; 22 | field=val; 23 | otherField = val; 24 | 25 | 26 | return prev; 27 | 28 | } 29 | } 30 | 31 | doSomething() { 32 | // Normal property access 33 | SomeClass a = new SomeClass(); 34 | SomeClass b = new SomeClass(); 35 | 36 | String f = a.parent.parent.field; 37 | 38 | String g = a.field; 39 | String h = a.otherField; 40 | 41 | var c = a as dynamic; 42 | 43 | // Prefixed expre that's not a property 44 | var d = m.E; 45 | 46 | // unknown property access 47 | String f1 = c.parent.parent.field; 48 | 49 | String g1 = c.field; 50 | 51 | // Cascading 52 | SomeClass x = new SomeClass() 53 | ..parent = (new SomeClass()..field = "pippo") 54 | ..parent.field = "Fino" 55 | ..otherField = "ciccio" 56 | ..field = "pluto"; 57 | 58 | // Cascading with unknown 59 | var y = (x as dynamic) 60 | ..parent = (new SomeClass()..field = "pippo") 61 | ..parent.field = "pino" 62 | ..otherField = "brook" 63 | ..field = "pluto"; 64 | } 65 | -------------------------------------------------------------------------------- /e2e_test/lib/strange_prefix_case.dart: -------------------------------------------------------------------------------- 1 | void strangePrefix([num x=-1,num y=1]) { 2 | print("${x} is a prefix expression?"); 3 | } -------------------------------------------------------------------------------- /e2e_test/lib/test.ts: -------------------------------------------------------------------------------- 1 | export class SampleClass { 2 | 3 | get doc() { 4 | return module.document; 5 | } 6 | } 7 | 8 | 9 | export class OtherClass extends SampleClass { 10 | 11 | } 12 | 13 | export class Module { 14 | get document() { 15 | return "ciao"; 16 | } 17 | 18 | } 19 | 20 | 21 | export var module = new Module(); -------------------------------------------------------------------------------- /e2e_test/lib/test2.ts: -------------------------------------------------------------------------------- 1 | import * as lib1 from "./test"; 2 | 3 | 4 | var x:lib1.SampleClass = new lib1.SampleClass(); 5 | console.log(`${x.doc===lib1.module.document} is true`); 6 | -------------------------------------------------------------------------------- /e2e_test/lib/test3.ts: -------------------------------------------------------------------------------- 1 | export class My { 2 | xx: number; 3 | 4 | * generatorMethod() { 5 | yield this.xx++; 6 | yield this.xx++; 7 | yield this.xx++; 8 | } 9 | 10 | 11 | executeMe() { 12 | this.xx = 10; 13 | var x = () => { 14 | return (function* () { 15 | while (this.xx < 20) { 16 | yield this.xx++; 17 | } 18 | }).call(this); 19 | }; 20 | 21 | for (let n of x()) { 22 | console.log(`val : ${n}`); 23 | } 24 | } 25 | } 26 | 27 | 28 | function makeIndexAwareProxy(claxx: X) { 29 | return new Proxy(claxx, { 30 | construct(target, args) { 31 | return new Proxy(new (target as any)(...args), { 32 | 33 | }); 34 | } 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /e2e_test/lib/test4.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Exporing a new way for classes and modules 3 | */ 4 | 5 | export class _MyClass { 6 | field1: X; 7 | static STATIC: number = 10; 8 | 9 | method1(y: Y): Array { 10 | return []; 11 | } 12 | 13 | static get anotherConstructor(): MyClass$anotherConstructor { 14 | let ctor = function (this: _MyClass, x: X) { 15 | this.field1 = x; 16 | }; 17 | ctor.prototype = _MyClass.prototype; 18 | return ctor as any as MyClass$anotherConstructor; 19 | } 20 | 21 | constructor() { 22 | 23 | } 24 | } 25 | 26 | export interface MyClass$anotherConstructor { 27 | new(x: X): _MyClass; 28 | } 29 | 30 | export interface MyClass$Static { 31 | 32 | } 33 | 34 | export interface MyClass$Constructor extends MyClass$Static { 35 | 36 | new(): _MyClass; 37 | } 38 | 39 | /** 40 | * Derived class 41 | */ 42 | 43 | export class _MyOtherClass extends module.MyClass> { 44 | anotherField: X; 45 | 46 | method2(x1: X, x2: X): Array> { 47 | return super.method1(x1); 48 | } 49 | 50 | constructor(x: X) { 51 | super(); 52 | this.field1 = x; 53 | this.anotherField = x; 54 | } 55 | } 56 | 57 | export interface MyOtherClass$Constructor extends MyClass$Static { 58 | new(x: X): _MyOtherClass; 59 | } 60 | 61 | /** 62 | * Mofulr 63 | * @type {{MyClass(): MyClass$Constructor; MyOtherClass(): MyOtherClass$Constructor}} 64 | */ 65 | 66 | var module = { 67 | get MyClass(): MyClass$Constructor { 68 | return _MyClass; 69 | }, 70 | 71 | get MyOtherClass(): MyOtherClass$Constructor { 72 | return _MyOtherClass; 73 | } 74 | }; 75 | 76 | export default module; -------------------------------------------------------------------------------- /e2e_test/lib/test_anno.dart: -------------------------------------------------------------------------------- 1 | import 'package:js/js.dart'; 2 | import 'package:dart2ts/annotations.dart'; 3 | 4 | class MyAnnotation { 5 | final String _value; 6 | 7 | const MyAnnotation(this._value); 8 | } 9 | 10 | @MyAnnotation('Yeah!') 11 | class MyAnnotatedClass { 12 | @MyAnnotation('onprop') 13 | String myProp; 14 | } 15 | 16 | @JS("Map") 17 | class JSMap { 18 | @JS('get') 19 | external V GET(K str); 20 | } 21 | 22 | @JS() 23 | @anonymous 24 | @Module('sdk:utils') 25 | class IAnnotationKey { 26 | String library; 27 | String type; 28 | 29 | IAnnotationKey({this.library, this.type}); 30 | } 31 | 32 | @JS() 33 | @Module('sdk:utils') 34 | class IAnnotation { 35 | String library; 36 | String type; 37 | var value; 38 | } 39 | 40 | @JS('Metadata') 41 | @Module('sdk:utils') 42 | class IDartMetadata { 43 | List annotations; 44 | JSMap> propertyAnnotations; 45 | } 46 | 47 | @JS('getMetadata') 48 | @Module('sdk:utils') 49 | external IDartMetadata getMetadata(var tp); 50 | 51 | IDartMetadata testMetadata() => getMetadata(MyAnnotatedClass); 52 | 53 | propAnno() => getMetadata(MyAnnotatedClass) 54 | .propertyAnnotations 55 | .GET('myProp') 56 | .GET('{asset:sample_project/lib/test_anno.dart}#{MyAnnotation}'); 57 | -------------------------------------------------------------------------------- /e2e_test/lib/test_async.dart: -------------------------------------------------------------------------------- 1 | part of 'sample1.dart'; 2 | 3 | Future> testAsync() => 4 | Future.wait(new List.generate(5, (i) => new Future.delayed(new Duration(seconds: i), () => i))); 5 | 6 | 7 | testAwait() async => 8 | [0,1,2,3,4] == await testAsync(); 9 | -------------------------------------------------------------------------------- /e2e_test/lib/test_async_closure.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | /** 4 | * export var doAsync: () => any = () => new async.Future.fromPromise((async (): Promise => { 5 | let result: string = await (() => new async.Future.fromPromise((async (): Promise => { 6 | return "hi"; 7 | })()))(); 8 | return result; 9 | })()); 10 | */ 11 | doAsync(String salute, String name) async { 12 | String result = await ((String name) async { 13 | return "${salute} ${name}"; 14 | })(name); 15 | 16 | return result; 17 | } 18 | 19 | Stream doAsyncStream(String name) { 20 | String salute = "Hi"; 21 | return ((String name) async* { 22 | for (int i = 0; i < 3; i++) { 23 | await new Future.delayed(new Duration(seconds: 1)); 24 | yield await doAsync(salute, name); 25 | } 26 | })(name); 27 | } 28 | 29 | testStream() { 30 | return doAsyncStream("Jhon").join(','); 31 | } 32 | -------------------------------------------------------------------------------- /e2e_test/lib/test_cascading.dart: -------------------------------------------------------------------------------- 1 | class MyClaz { 2 | String value; 3 | MyClaz another; 4 | Function func; 5 | Function func2; 6 | 7 | void setValue(String v) { 8 | value = v; 9 | } 10 | } 11 | 12 | class Another { 13 | String funcAnother() { 14 | return "Hi"; 15 | } 16 | } 17 | 18 | testCascading() { 19 | Another another = new Another(); 20 | return new MyClaz() 21 | ..setValue('ciao') 22 | ..another = (new MyClaz()..value = "Ugo") 23 | ..func = ((String x) { 24 | String y = "${x}!"; 25 | return y; 26 | }) 27 | ..func2 = (() { 28 | return another.funcAnother(); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /e2e_test/lib/test_declOrder.dart: -------------------------------------------------------------------------------- 1 | class ChildClass extends ParentClass { 2 | 3 | } 4 | 5 | class ParentClass { 6 | 7 | } -------------------------------------------------------------------------------- /e2e_test/lib/test_initializers.dart: -------------------------------------------------------------------------------- 1 | class X { 2 | int a=1,b=2,c=3; 3 | X(); 4 | 5 | int met() { 6 | int x=0,y=1; 7 | return x+y+a+b+c; 8 | } 9 | } 10 | 11 | X x = new X(); -------------------------------------------------------------------------------- /e2e_test/lib/test_js_anno.dart: -------------------------------------------------------------------------------- 1 | import 'package:js/js.dart'; 2 | 3 | import 'mini_html.dart'; 4 | 5 | class MyClass { 6 | @JS('otherName') 7 | static String myName = 'hi'; 8 | } 9 | 10 | abstract class OtherClass extends HTMLElement { 11 | void testExtAnno() { 12 | HTMLElement div1 = document.createElement('div'); 13 | HTMLElement div2 = createDiv(); 14 | 15 | div1.appendChild(div2); 16 | 17 | window.scroll(10, 20); 18 | } 19 | } 20 | 21 | class AutoRefParent { 22 | AutoRef x; 23 | int c = 0; 24 | 25 | void doIt() { 26 | c++; 27 | } 28 | } 29 | 30 | class AutoRef extends AutoRefParent { 31 | AutoRef autoRefProp() { 32 | AutoRef ref = new AutoRef(); 33 | ref.x = x; // reference to x that's also an class method 34 | ref.x.x = x.x; // move a3 -> a3 35 | ref.doIt(); // ref.c = 1 36 | var dynRef = ref as dynamic; 37 | dynRef.x = this; // reference to x that's also an class method , 38 | dynRef.doIt(); // rec.c = 2 39 | 40 | Function mRef = ref.x.doIt; 41 | Function mRef2 = doIt; 42 | Function mRef3 = ref.doIt; 43 | 44 | mRef(); // ref.x.c=1 45 | mRef2(); // ref.x.c=2 46 | mRef3(); // ref.c = 3 47 | 48 | return ref; 49 | } 50 | } 51 | 52 | AutoRef testRefs() { 53 | AutoRef a1 = new AutoRef(); 54 | AutoRef a2 = new AutoRef(); 55 | AutoRef a3 = new AutoRef(); 56 | a1.x = a2; 57 | a2.x = a3; 58 | 59 | return a1.autoRefProp(); 60 | } 61 | -------------------------------------------------------------------------------- /e2e_test/lib/test_map.dart: -------------------------------------------------------------------------------- 1 | testMap() { 2 | Map simpleMap = new Map(); 3 | simpleMap['ciao'] = 1; 4 | 5 | Map> m = { 6 | "one": { 7 | "alpha": 1, 8 | "beta": 2, 9 | }, 10 | "two": { 11 | "gamma": 3, 12 | "delta": 4, 13 | } 14 | }; 15 | 16 | return m['two']['gamma']; 17 | } 18 | -------------------------------------------------------------------------------- /e2e_test/lib/test_operator.dart: -------------------------------------------------------------------------------- 1 | testSomeOps() { 2 | bool a = false; 3 | 4 | var b; 5 | if (!a) { 6 | b=false; 7 | } else { 8 | b=true; 9 | } 10 | 11 | if (!b) { 12 | return 10; 13 | } else { 14 | return 20; 15 | } 16 | } -------------------------------------------------------------------------------- /e2e_test/lib/test_strange.dart: -------------------------------------------------------------------------------- 1 | abstract class MyInterface { 2 | X get x; 3 | 4 | factory MyInterface(X val) = MyImpl; 5 | 6 | factory MyInterface.named({X x}) = MyImpl.named; 7 | } 8 | 9 | class MyImpl implements MyInterface { 10 | Y x; 11 | 12 | @override 13 | MyImpl(Y val) { 14 | this.x = val; 15 | } 16 | 17 | MyImpl.named({this.x}) {} 18 | } 19 | 20 | int test1(int val) { 21 | return new MyInterface(val).x; 22 | } 23 | 24 | int test2(int val) { 25 | return new MyInterface.named(x: val).x; 26 | } 27 | 28 | String test3() { 29 | String x = "value1"; 30 | 31 | x ??= "value2"; 32 | 33 | return x; 34 | } 35 | 36 | int test4(y) { 37 | return (y?.length) ?? -1; 38 | } 39 | 40 | int test5(y) { 41 | return ((y?.toString() as dynamic)?.length) ?? -1; 42 | } 43 | 44 | class Pippo { 45 | doNothing() {} 46 | 47 | Pippo getParent() => null; 48 | 49 | String doHello(String name) => "Hello ${name}"; 50 | } 51 | 52 | String test6(Pippo p, String name) { 53 | return p?.doHello(name); 54 | } 55 | 56 | String test7(Pippo p, String name) { 57 | return p?.getParent()?.doHello(name); 58 | } 59 | -------------------------------------------------------------------------------- /e2e_test/lib/test_stream.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | testDaStream() async { 4 | startStream1(StreamController controller) async { 5 | for (int i = 0; i < 10; i++) { 6 | controller.add("Event ${i}"); 7 | await new Future.delayed(new Duration(milliseconds: 50)); 8 | } 9 | controller.close(); 10 | } 11 | 12 | startStream2(StreamController controller) async { 13 | for (int i = 0; i < 10; i++) { 14 | await new Future.delayed(new Duration(milliseconds: 50)); 15 | controller.add("Event ${i}"); 16 | } 17 | controller.close(); 18 | } 19 | 20 | await execStreamOnListen(startStream1); 21 | 22 | await execStream(startStream1); 23 | 24 | await execStream(startStream2); 25 | 26 | await execStream(startStream1, 5); 27 | 28 | await execStream(startStream2, 5); 29 | 30 | // Now with onListen 31 | } 32 | 33 | Future execStreamOnListen(void source(StreamController c), [int max]) async { 34 | StreamController controller; 35 | controller = new StreamController.broadcast(onListen: () => source(controller), onCancel: () => print('CANCEL'),sync:false); 36 | 37 | print('start receiving'); 38 | await for (String event in controller.stream) { 39 | print("Received : ${event}"); 40 | if (max != null) { 41 | if (max-- <= 0) { 42 | break; 43 | } 44 | } 45 | } 46 | print('finished receiving'); 47 | } 48 | 49 | Future execStream(void source(StreamController c), [int max]) async { 50 | StreamController controller = new StreamController.broadcast(); 51 | source(controller); 52 | 53 | print('start receiving'); 54 | await for (String event in controller.stream) { 55 | print("Received : ${event}"); 56 | if (max != null) { 57 | if (max-- <= 0) { 58 | break; 59 | } 60 | } 61 | } 62 | print('finished receiving'); 63 | } 64 | -------------------------------------------------------------------------------- /e2e_test/lib/test_stringCtor.dart: -------------------------------------------------------------------------------- 1 | String createAString() { 2 | return new String.fromCharCode(10); 3 | } -------------------------------------------------------------------------------- /e2e_test/lib/test_unicodeEscape.dart: -------------------------------------------------------------------------------- 1 | String string4='HH \'h\' mm \'min\' ss \'s\' zzzz'; 2 | String string1='\u0660'; 3 | String string2=' \'ч\' '; 4 | String string3='\u09E6'; 5 | -------------------------------------------------------------------------------- /e2e_test/lib/tests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sample 5 | 11 | 12 | 13 | 33 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /e2e_test/lib/try_catch.dart: -------------------------------------------------------------------------------- 1 | int doSomethingBadFinally = 0; 2 | 3 | doSomethingBad(String str) { 4 | try { 5 | return "${str.length}"; 6 | } on NullThrownError catch (e) { 7 | return e.toString(); 8 | } catch (error, stack) { 9 | return "${error}:${stack}"; 10 | } finally { 11 | doSomethingBadFinally++; 12 | } 13 | } 14 | 15 | int doSomethingElseNoCatchFinally = 0; 16 | doSomethingElseNoCatch(String str) { 17 | try { 18 | return str.length; 19 | } on NullThrownError { 20 | return -1; 21 | } catch (rest) { 22 | return -2; 23 | } finally { 24 | doSomethingElseNoCatchFinally++; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /e2e_test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "e2e_test", 3 | "version": "1.0.0", 4 | "description": "a test for it", 5 | "main": "lib/index.html", 6 | "flat": true, 7 | "scripts": { 8 | "build": "tsc", 9 | "serve": "webpack-dev-server --config ./webpack.config.js", 10 | "dist": "webpack --config ./webpack.config.js" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@dart2ts/dart": "^0.1.22", 16 | "reflect-metadata": "^0.1.12" 17 | }, 18 | "devDependencies": { 19 | "clean-webpack-plugin": "^0.1.19", 20 | "copy-webpack-plugin": "^4.5.2", 21 | "expose-loader": "^0.7.5", 22 | "html-loader": "^0.5.5", 23 | "html-webpack-plugin": "^3.2.0", 24 | "ts-loader": "^5.2.1", 25 | "typescript": "^3.1.1", 26 | "wct-browser-legacy": "^1.0.2", 27 | "webpack": "^4.20.2", 28 | "webpack-cli": "^3.1.2", 29 | "webpack-dev-server": "^3.1.9", 30 | "growl": ">=1.10.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /e2e_test/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: sample_project 2 | description: sample_project to be translated 3 | version: 0.0.1 4 | dependencies: 5 | js: any 6 | dev_dependencies: 7 | dart2ts: 8 | path: ../dart2ts 9 | -------------------------------------------------------------------------------- /e2e_test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "es6", 4 | "target": "es6", 5 | "sourceMap": true, 6 | "declaration": true, 7 | "rootDir":"./", 8 | "outDir":"./dist", 9 | "experimentalDecorators" :true, 10 | "moduleResolution": "node", 11 | "strict": true, 12 | /* Enable all strict type-checking options. */ 13 | "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ 14 | "strictNullChecks": false, /* Enable strict null checks. */ 15 | "strictPropertyInitialization":false, 16 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 17 | "noImplicitThis": false, /* Raise error on 'this' expressions with an implied 'any' type. */ 18 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 19 | "lib": [ 20 | "dom", 21 | "es6", 22 | "esnext.asynciterable" 23 | ] 24 | }, 25 | "include": [ 26 | "lib/**/*.ts" 27 | ] 28 | } 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /e2e_test/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 5 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 6 | const webpack = require('webpack'); 7 | 8 | module.exports = { 9 | entry: { 10 | app: [ 11 | 'webpack-dev-server/client?http://localhost:9000', 12 | './lib/index' 13 | ], 14 | test: [ 15 | 'webpack-dev-server/client?http://localhost:9000', 16 | /*'./lib/exports'*/ 17 | 'expose-loader?tests!./lib/exports' 18 | ] 19 | 20 | }, 21 | devtool: 'inline-source-map', 22 | devServer: { 23 | contentBase: path.resolve(__dirname, 'dist'), 24 | hot: true, 25 | port: 9000 26 | }, 27 | output: { 28 | filename: '[name].js', 29 | chunkFilename: '[name].bundle.js', 30 | 31 | path: path.resolve(__dirname, 'dist') 32 | }, 33 | optimization: { 34 | splitChunks: { 35 | chunks: 'all' 36 | } 37 | }, 38 | module: { 39 | rules: [ 40 | { 41 | test: /\.(html)$/, 42 | use: { 43 | loader: 'html-loader' 44 | } 45 | }, 46 | { 47 | test: /\.ts?$/, 48 | use: 'ts-loader', 49 | exclude: /node_modules/ 50 | } 51 | ] 52 | }, 53 | resolve: { 54 | extensions: ['.ts', '.js'] 55 | }, 56 | plugins: [ 57 | new CleanWebpackPlugin(['dist'], { verbose: false, root: path.resolve(__dirname) }), 58 | new HtmlWebpackPlugin({ 59 | template: './lib/tests.html', 60 | filename: "tests.html", 61 | chunks: ['test', 'vendors~app~test'], 62 | inject: "body" 63 | }), 64 | new HtmlWebpackPlugin({ 65 | template: './lib/index.html', 66 | chunks: ['app', 'vendors~app~test'], 67 | inject: "body" 68 | }), 69 | new webpack.HotModuleReplacementPlugin(), 70 | ] 71 | }; 72 | -------------------------------------------------------------------------------- /e2e_test/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "dart_sdk@file:../dart_sdk/dist": 6 | version "0.0.1" 7 | dependencies: 8 | reflect-metadata "^0.1.12" 9 | 10 | reflect-metadata@^0.1.12: 11 | version "0.1.12" 12 | resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" 13 | 14 | typescript@^2.7.2: 15 | version "2.7.2" 16 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" 17 | -------------------------------------------------------------------------------- /polymer2/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /polymer2/dart2ts.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:dart2ts/dart2ts.dart'; 3 | 4 | Future main() async { 5 | await tsbuild(clean: true); 6 | } 7 | -------------------------------------------------------------------------------- /polymer2/dist/.gitignore: -------------------------------------------------------------------------------- 1 | lib -------------------------------------------------------------------------------- /polymer2/dist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer2", 3 | "version": "0.0.1", 4 | "description": "Polymer support for dart2ts", 5 | "flat": "true", 6 | "scripts": { 7 | "build": "tsc" 8 | }, 9 | "files": [ 10 | "lib/**/*.js", 11 | "lib/**/*.d.ts", 12 | "package.json" 13 | ], 14 | "author": "vittorio.ballestra@gmail.com", 15 | "license": "ISC", 16 | "dependencies": { 17 | "dart_sdk": "file:../dart_sdk/dist", 18 | "html5": "file:../../html5/dist" 19 | }, 20 | "devDependencies": { 21 | "typescript": "^2.5.2" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /polymer2/lib/.gitignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | -------------------------------------------------------------------------------- /polymer2/lib/polymer2.dart: -------------------------------------------------------------------------------- 1 | export "src/annotations.dart"; 2 | export "src/element.dart"; 3 | export "src/polymer_support.dart"; 4 | -------------------------------------------------------------------------------- /polymer2/lib/src/annotations.dart: -------------------------------------------------------------------------------- 1 | class PolymerRegister { 2 | final String tagName; 3 | final String template; 4 | final bool native; 5 | final List uses; 6 | 7 | const PolymerRegister(this.tagName, {this.template, this.native: false, this.uses}); 8 | } 9 | 10 | class BowerImport { 11 | final String ref; 12 | final String path; 13 | final String name; 14 | 15 | const BowerImport({this.ref, this.path, this.name}); 16 | } 17 | 18 | /** 19 | * Optional property annotation in order to add metadata info. 20 | */ 21 | class Property { 22 | final bool notify; 23 | 24 | /// TODO: not yet implemented 25 | final String computed; 26 | final String statePath; 27 | 28 | /// TODO: not yet implemented 29 | final Function statePathSelector; 30 | 31 | /// TODO: not yet implemented 32 | final Map extra; 33 | 34 | const Property({this.notify: false, this.computed, this.statePath, this.extra, this.statePathSelector}); 35 | } 36 | 37 | /*** 38 | * Mark a class to become a polymer mixin. 39 | * Classes marked with this annotation becomes a js-mixin (a la polymer) 40 | * and can be used in `implements` clause like any other polymer mixin. 41 | * This functionality replaces the dart mixin feature in a way that is more 42 | * js interoperable. 43 | */ 44 | class PolymerBehavior { 45 | final String name; 46 | 47 | const PolymerBehavior(this.name); 48 | } 49 | 50 | class Observe { 51 | final String observed; 52 | 53 | const Observe(this.observed); 54 | } 55 | 56 | class Notify { 57 | const Notify(); 58 | } 59 | 60 | const Notify notify = const Notify(); 61 | -------------------------------------------------------------------------------- /polymer2/lib/src/element.dart: -------------------------------------------------------------------------------- 1 | @JS('Polymer') 2 | library polymer2.lib.src.element; 3 | 4 | import 'package:html5/html.dart'; 5 | import 'package:js/js.dart'; 6 | import 'package:polymer2/src/annotations.dart'; 7 | import 'package:dart2ts/annotations.dart'; 8 | 9 | @JS() 10 | @TS(generate: true) 11 | @BowerImport( 12 | ref: 'polymer#2.5.0', name: 'polymer', path: 'polymer/polymer.html') 13 | abstract class Element extends HTMLElement { 14 | get(String path); 15 | 16 | set(String path, value); 17 | 18 | notifyPath(String path); 19 | } 20 | -------------------------------------------------------------------------------- /polymer2/lib/src/polymer_support.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | @Module('polymer2/lib/src/polymer_support_native') 3 | library polymer2.lib.src.polymer_support; 4 | 5 | import 'package:js/js.dart'; 6 | import 'package:dart2ts/annotations.dart'; 7 | 8 | @JS() 9 | external register(Type dartClass, [String tagName]); 10 | -------------------------------------------------------------------------------- /polymer2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer2", 3 | "version": "0.0.1", 4 | "description": "Polymer support for dart2ts", 5 | "flat": "true", 6 | "scripts": { 7 | "build": "tsc" 8 | }, 9 | "files": [ 10 | "lib/**/*.js", 11 | "lib/**/*.d.ts", 12 | "package.json" 13 | ], 14 | "author": "vittorio.ballestra@gmail.com", 15 | "license": "ISC", 16 | "dependencies": { 17 | "dart_sdk": "file:../dart_sdk/dist", 18 | "html5": "file:../../html5/dist" 19 | }, 20 | "devDependencies": { 21 | "typescript": "^2.5.2" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /polymer2/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: polymer2 2 | version: 0.1.0 3 | description: Polymer2 Support for dart2ts 4 | dependencies: 5 | html5: any 6 | dev_dependencies: 7 | dart2ts: 8 | path: ../dart2ts 9 | dependency_overrides: 10 | html5: 11 | path: ../../html5 12 | 13 | environment: 14 | sdk: ">=1.8.0 <2.0.0" 15 | -------------------------------------------------------------------------------- /polymer2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "es6", 4 | "target": "es6", 5 | "sourceMap": true, 6 | "declaration": true, 7 | "rootDir": "./", 8 | "outDir": "dist", 9 | "baseUrl": "./", 10 | "experimentalDecorators": true, 11 | "lib": [ 12 | "dom", 13 | "es6", 14 | "esnext.asynciterable" 15 | ] 16 | }, 17 | "exclude": [ 18 | "node_modules", 19 | "dist" 20 | ], 21 | "include": [ 22 | "lib/**/*.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /polymer2/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "dart_sdk@file:../dart_sdk/dist": 6 | version "0.0.1" 7 | dependencies: 8 | reflect-metadata "^0.1.12" 9 | 10 | "html5@file:../../html5/dist": 11 | version "0.0.1" 12 | 13 | reflect-metadata@^0.1.12: 14 | version "0.1.12" 15 | resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" 16 | 17 | typescript@^2.5.2: 18 | version "2.7.2" 19 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" 20 | -------------------------------------------------------------------------------- /polymer2_builder/lib/polymer2_builder.dart: -------------------------------------------------------------------------------- 1 | export 'src/builder.dart'; -------------------------------------------------------------------------------- /polymer2_builder/lib/src/builder.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:analyzer/dart/element/element.dart'; 4 | import 'package:build/build.dart'; 5 | import 'package:code_builder/code_builder.dart' as code_builder; 6 | import 'package:dart2ts/src/utils.dart'; 7 | import 'package:dart_style/dart_style.dart'; 8 | /* 9 | Future generateInitCode(PackageGraph graph) async { 10 | await build([new PackageBuildAction(new InitCodePackageBuilder(new Glob("lib/myelement.dart")), graph.root.name)], 11 | packageGraph: graph); 12 | }*/ 13 | 14 | class InitCodePackageBuilder extends Builder { 15 | InitCodePackageBuilder(); 16 | 17 | @override 18 | Future build(BuildStep buildStep) async { 19 | code_builder.FileBuilder fileBuilder = new code_builder.FileBuilder(); 20 | code_builder.BlockBuilder blockBuilder = new code_builder.BlockBuilder(); 21 | code_builder.MethodBuilder methodBuilder = new code_builder.MethodBuilder() 22 | ..name = '_registerAllComponents' 23 | ..annotations.add(code_builder.refer("onModuleLoad", "package:dart2ts/annotations.dart").annotation()); 24 | 25 | Iterable allDeps(LibraryElement le, Set visited) sync* { 26 | if (visited.contains(le.id)) { 27 | return; 28 | } 29 | 30 | visited.add(le.id); 31 | 32 | for (LibraryElement imported in le.importedLibraries) { 33 | yield* allDeps(imported, visited); 34 | } 35 | 36 | yield le; 37 | } 38 | 39 | // If it's a lib 40 | if (!await buildStep.resolver.isLibrary(buildStep.inputId)) { 41 | return; 42 | } 43 | 44 | // Collect every component 45 | LibraryElement libraryElement = await buildStep.resolver.libraryFor(buildStep.inputId); 46 | 47 | allDeps(libraryElement, new Set()).forEach((lib) { 48 | // find all classes annotated with polymer register 49 | 50 | lib.units.forEach((cu) { 51 | cu.types.forEach((ce) { 52 | if (getAnnotation(ce.metadata, isPolymerRegister2) != null) { 53 | blockBuilder.addExpression(code_builder 54 | .refer("register", "package:polymer2/polymer2.dart") 55 | .call([code_builder.refer(ce.name, toPackageUri(ce.library.source.uri))])); 56 | } 57 | }); 58 | }); 59 | }); 60 | 61 | methodBuilder.body = blockBuilder.build(); 62 | fileBuilder.body.add(methodBuilder.build()); 63 | 64 | code_builder.File library = fileBuilder.build(); 65 | 66 | final emitter = new code_builder.DartEmitter(new code_builder.Allocator.simplePrefixing()); 67 | await buildStep.writeAsString( 68 | buildStep.inputId.changeExtension('.init.dart'), new DartFormatter().format('${library.accept(emitter)}')); 69 | } 70 | 71 | @override 72 | Iterable get outputs => const ['lib/init.dart']; 73 | 74 | // TODO: implement buildExtensions 75 | @override 76 | Map> get buildExtensions => const { 77 | '.dart': const ['.init.dart'] 78 | }; 79 | } 80 | 81 | String toPackageUri(Uri assetUri) { 82 | AssetId id = new AssetId.resolve(assetUri.toString()); 83 | return "package:${id.package}/${id.path.split('/').sublist(1).join('/')}"; 84 | } 85 | -------------------------------------------------------------------------------- /polymer2_builder/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: polymer2_builder 2 | version: 0.1.0 3 | description: Polymer2 Support for dart2ts 4 | dependencies: 5 | html5: any 6 | dev_dependencies: 7 | dart2ts: 8 | path: ../dart2ts 9 | build: ">=0.11.2" 10 | build_runner: ">=0.6.1" 11 | analyzer: ">=0.30.0 <0.32.0" 12 | polymer2: 13 | path: ../polymer2 14 | dependency_overrides: 15 | html5: 16 | path: ../../html5 17 | 18 | 19 | environment: 20 | sdk: ">=1.8.0 <2.0.0" 21 | -------------------------------------------------------------------------------- /polymer2_test/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dart_sdk 3 | bower_components -------------------------------------------------------------------------------- /polymer2_test/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer_test", 3 | "description": "a polymer 2 sample with dart2ts", 4 | "main": "lib/index.html", 5 | "authors": [ 6 | "Vittorio Ballestra " 7 | ], 8 | "license": "ISC", 9 | "homepage": "https://github.com/polymer-dart/dart2ts", 10 | "ignore": [ 11 | "**/.*", 12 | "node_modules", 13 | "bower_components", 14 | "test", 15 | "tests" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /polymer2_test/build.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart2ts/dart2ts.dart'; 2 | import 'package:build_runner/build_runner.dart'; 3 | import 'dart:async'; 4 | import 'package:glob/glob.dart'; 5 | import 'package:polymer2_builder/polymer2_builder.dart'; 6 | 7 | Future main(List args) async { 8 | BuildResult res = await build([ 9 | new BuildAction(new InitCodePackageBuilder(), 'polymer2_test', inputs: ['lib/myelement.dart']), 10 | new BuildAction(new Dart2TsBuilder(), 'polymer2_test', inputs: ['lib/**.dart']), 11 | ], deleteFilesByDefault: true); 12 | 13 | if (res.status == BuildStatus.success) { 14 | await tsc(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /polymer2_test/lib/.gitignore: -------------------------------------------------------------------------------- 1 | myelement.ts 2 | myelement.js 3 | myelement.js.map 4 | myelement.d.ts 5 | myelement.init.ts 6 | myelement.init.js 7 | myelement.init.js.map 8 | -------------------------------------------------------------------------------- /polymer2_test/lib/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 25 |
26 | 27 |
28 |
29 | 30 |
31 | 32 | -------------------------------------------------------------------------------- /polymer2_test/lib/myelement.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart2ts/annotations.dart'; 2 | import 'package:html5/html.dart'; 3 | import 'package:polymer2/polymer2.dart' as polymer; 4 | import 'package:js/js.dart'; 5 | 6 | @polymer.PolymerRegister('my-tag', template: 'myelement.html') 7 | abstract class MyElement extends polymer.Element { 8 | String name; 9 | @polymer.Property(notify: true) 10 | int number = 0; 11 | 12 | //@JS('is') 13 | //static String _tagName = 'my-tag'; 14 | 15 | MyElement() { 16 | name = "Pino" " Daniele " "Lives!"; 17 | } 18 | 19 | void changeName(Event ev, detail) { 20 | ev.preventDefault(); 21 | ev.stopPropagation(); 22 | print('Clicked : ${ev}, ${detail}'); 23 | //number = number + 1; 24 | name = 'Super app : ${number++}'; 25 | } 26 | } -------------------------------------------------------------------------------- /polymer2_test/lib/myelement.html: -------------------------------------------------------------------------------- 1 | 2 | 17 | -------------------------------------------------------------------------------- /polymer2_test/lib/myelement.init.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart2ts/annotations.dart' as _1; 2 | import 'package:polymer2/polymer2.dart' as _2; 3 | import 'package:polymer2_test/myelement.dart' as _3; 4 | 5 | @_1.onModuleLoad 6 | _registerAllComponents() { 7 | _2.register(_3.MyElement); 8 | } 9 | -------------------------------------------------------------------------------- /polymer2_test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer_test", 3 | "flat": true, 4 | "version": "1.0.0", 5 | "description": "a test for it", 6 | "main": "lib/index.html", 7 | "scripts": { 8 | "srv": "python -m http.server 8000", 9 | "polyserv": "polymer serve" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "dart_sdk": "file:../dart_sdk/dist", 15 | "html5": "file:../../html5/dist", 16 | "polymer2": "file:../polymer2/dist", 17 | "reflect-metadata": "^0.1.12" 18 | }, 19 | "devDependencies": { 20 | "ts-loader": "^2.3.7", 21 | "typescript": "^2.7.1", 22 | "webpack": "^3.10.0", 23 | "webpack-dev-server": "^2.11.1" 24 | }, 25 | "resolutions": { 26 | "supports-color": "5.2.0", 27 | "has-flag": "3.0.0", 28 | "inherits": "2.0.3", 29 | "acorn": "5.5.0", 30 | "ajv": "6.2.0", 31 | "async": "2.6.0", 32 | "source-map": "0.6.1", 33 | "yargs": "8.0.2", 34 | "minimist": "1.2.0", 35 | "punycode": "1.3.2", 36 | "hash-base": "3.0.4", 37 | "camelcase": "4.1.0", 38 | "cliui": "3.2.0", 39 | "lazy-cache": "2.0.2", 40 | "kind-of": "6.0.2", 41 | "braces": "2.3.1", 42 | "glob-parent": "3.1.0", 43 | "is-glob": "4.0.0", 44 | "micromatch": "3.1.9", 45 | "arr-diff": "4.0.0", 46 | "array-unique": "0.3.2", 47 | "define-property": "2.0.2", 48 | "extend-shallow": "3.0.2", 49 | "extglob": "2.0.4", 50 | "is-descriptor": "1.0.2", 51 | "isobject": "3.0.1", 52 | "is-accessor-descriptor": "1.0.0", 53 | "is-data-descriptor": "1.0.0", 54 | "is-extendable": "1.0.1", 55 | "expand-brackets": "2.1.4", 56 | "debug": "3.1.0", 57 | "is-number": "4.0.0", 58 | "has-value": "1.0.0", 59 | "set-value": "2.0.0", 60 | "has-values": "1.0.0", 61 | "fill-range": "4.0.0", 62 | "is-extglob": "2.1.1", 63 | "string-width": "2.1.1", 64 | "strip-ansi": "4.0.0", 65 | "is-fullwidth-code-point": "2.0.0", 66 | "ansi-regex": "3.0.0", 67 | "qs": "6.5.1", 68 | "assert-plus": "1.0.0", 69 | "extsprintf": "1.3.0", 70 | "os-locale": "2.1.0", 71 | "read-pkg-up": "2.0.0", 72 | "which-module": "2.0.0", 73 | "yargs-parser": "7.0.0", 74 | "find-up": "2.1.0", 75 | "read-pkg": "2.0.0", 76 | "path-exists": "3.0.0", 77 | "load-json-file": "2.0.0", 78 | "path-type": "2.0.0", 79 | "pify": "3.0.0", 80 | "strip-bom": "3.0.0", 81 | "array-flatten": "2.1.1", 82 | "depd": "1.1.2", 83 | "setprototypeof": "1.1.0", 84 | "statuses": "1.4.0", 85 | "mime": "1.6.0", 86 | "faye-websocket": "0.11.1", 87 | "url-parse": "1.2.0", 88 | "querystringify": "1.0.0" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /polymer2_test/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: polymer2_test 2 | description: sample_project to be translated 3 | version: 0.0.1 4 | dependencies: 5 | js: any 6 | html5: any 7 | polymer2: 8 | path: ../polymer2 9 | #polymerize: any 10 | analyzer: ">=0.30.0 <0.32.0" 11 | dependency_overrides: 12 | html5: 13 | path: ../../html5 14 | dev_dependencies: 15 | polymer2_builder: 16 | path: ../polymer2_builder 17 | dart2ts: 18 | path: ../dart2ts 19 | -------------------------------------------------------------------------------- /polymer2_test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "es6", 4 | "target": "es6", 5 | "sourceMap": true, 6 | "declaration": true, 7 | "rootDir":"./lib/", 8 | "experimentalDecorators" :true, 9 | "lib": [ 10 | "dom", 11 | "es6", 12 | "esnext.asynciterable" 13 | ] 14 | }, 15 | "exclude": [ 16 | "node_modules" 17 | ], 18 | "include": [ 19 | "lib/**/*.ts" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /polymer_test/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dart_sdk -------------------------------------------------------------------------------- /polymer_test/build.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart2ts/dart2ts.dart'; 2 | import 'package:build_runner/build_runner.dart'; 3 | 4 | void main(List args) { 5 | build([ 6 | new BuildAction(new Dart2TsBuilder(), 'polymer_test', 7 | inputs: ['lib/**.dart']), 8 | ],deleteFilesByDefault: true); 9 | } 10 | -------------------------------------------------------------------------------- /polymer_test/dist/.gitignore: -------------------------------------------------------------------------------- 1 | bundle.js 2 | lib -------------------------------------------------------------------------------- /polymer_test/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Polymer Sample 5 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /polymer_test/lib/.gitignore: -------------------------------------------------------------------------------- 1 | html_template.ts 2 | mini_html.ts 3 | myelement.ts 4 | polymer.ts 5 | *.js 6 | *.js.map 7 | *.d.ts 8 | -------------------------------------------------------------------------------- /polymer_test/lib/html_template.dart: -------------------------------------------------------------------------------- 1 | import 'mini_html.dart'; 2 | import 'package:dart2ts/annotations.dart'; 3 | import 'polymer.dart' as polymer; 4 | 5 | @TS(stringInterpolation: true) 6 | HTMLTemplateElement html(String template, {List literals, List values}) { 7 | return polymer.html(literals, values); 8 | } -------------------------------------------------------------------------------- /polymer_test/lib/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 |
16 |
17 | 18 |
19 | 20 | -------------------------------------------------------------------------------- /polymer_test/lib/mini_html.dart: -------------------------------------------------------------------------------- 1 | import 'package:js/js.dart'; 2 | 3 | @JS() 4 | class CustomElementRegistry { 5 | external define(String tag, elementClass); 6 | } 7 | 8 | @JS() 9 | class HTMLElement { 10 | 11 | } 12 | 13 | @JS() 14 | external CustomElementRegistry get customElements; 15 | 16 | @JS() 17 | class HTMLTemplateElement { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /polymer_test/lib/myelement.dart: -------------------------------------------------------------------------------- 1 | import 'html_template.dart'; 2 | import 'mini_html.dart'; 3 | import 'package:dart2ts/annotations.dart'; 4 | import 'polymer.dart' as polymer; 5 | 6 | class MyElement extends polymer.Element { 7 | String name; 8 | int number = 0; 9 | 10 | static get template => html(""" 11 | 20 |
21 | This is my '[[name]]' app. 22 |
Click here Please
23 |
24 | """); 25 | 26 | MyElement() { 27 | name = "Pino" " Daniele " "Lives!"; 28 | } 29 | 30 | void changeName(ev, detail) { 31 | print('Clicked : ${ev}, ${detail}'); 32 | //number = number + 1; 33 | name = 'Super app : ${number++}'; 34 | } 35 | } 36 | 37 | @onModuleLoad 38 | void _registerElements() { 39 | customElements.define('my-tag', MyElement); 40 | } 41 | -------------------------------------------------------------------------------- /polymer_test/lib/polymer.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library polymer; 3 | 4 | import 'mini_html.dart'; 5 | import 'package:js/js.dart'; 6 | import 'package:dart2ts/annotations.dart'; 7 | 8 | @JS() 9 | @TS(generate: true, export: '@polymer/polymer/polymer-element') 10 | class Element extends HTMLElement {} 11 | 12 | @JS() 13 | @TS(generate: true) 14 | external HTMLTemplateElement html(List literals, @varargs List values); 15 | -------------------------------------------------------------------------------- /polymer_test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer_test", 3 | "flat": true, 4 | "version": "1.0.0", 5 | "description": "a test for it", 6 | "main": "lib/index.html", 7 | "scripts": { 8 | "build": "tsc", 9 | "serve": "polymer serve", 10 | "pserve": "python -m SimpleHTTPServer 8000" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@polymer/polymer": "^3.0.0-pre.9", 16 | "dart_sdk": "file:../dart_sdk/dist", 17 | "reflect-metadata": "^0.1.12" 18 | }, 19 | "devDependencies": { 20 | "ts-loader": "^2.3.7", 21 | "typescript": "^2.7.1", 22 | "polymer-cli": "^1.6.0", 23 | "webpack": "^3.10.0", 24 | "webpack-dev-server": "^2.11.1" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /polymer_test/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: polymer_test 2 | description: sample_project to be translated 3 | version: 0.0.1 4 | dependencies: 5 | js: any 6 | dart2ts: 7 | path: .. 8 | -------------------------------------------------------------------------------- /polymer_test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "es6", 4 | "target": "es6", 5 | "sourceMap": true, 6 | "declaration": true, 7 | "rootDir":"./", 8 | "experimentalDecorators" :true, 9 | "lib": [ 10 | "dom", 11 | "es6", 12 | "esnext.asynciterable" 13 | ] 14 | }, 15 | "exclude": [ 16 | "node_modules" 17 | ], 18 | "include": [ 19 | "lib/**/*.ts" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /polymer_test/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | /* 4 | module.exports = { 5 | entry: './lib/index.js', 6 | output: { 7 | filename: 'bundle.js', 8 | path: path.resolve(__dirname, 'dist') 9 | } 10 | }; 11 | */ 12 | module.exports = { 13 | entry: './lib/myelement.ts', 14 | devtool: 'inline-source-map', 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.tsx?$/, 19 | use: 'ts-loader', 20 | exclude: /node_modules/, 21 | } 22 | ] 23 | }, 24 | resolve: { 25 | modules: [path.resolve(__dirname, "lib"), "node_modules"], 26 | extensions: [".tsx", ".ts", ".js"] 27 | }, 28 | output: { 29 | filename: 'bundle.js', 30 | path: path.resolve(__dirname, 'dist') 31 | }, 32 | devServer: { 33 | contentBase: path.join(__dirname, "dist"), 34 | compress: true, 35 | port: 8081 36 | } 37 | }; 38 | 39 | 40 | 41 | --------------------------------------------------------------------------------