Adding the Flutter Sunflower test (#620)
diff --git a/lib/src/common.dart b/lib/src/common.dart
index 27e0be8..6efcb02 100644
--- a/lib/src/common.dart
+++ b/lib/src/common.dart
@@ -64,6 +64,435 @@
}
''';
+// From https://gist.github.com/johnpryan/b6409e10de32b280b8938aa75364fa7b
+const sampleCodeFlutterCounter = '''
+import 'package:flutter/material.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Flutter Demo',
+ debugShowCheckedModeBanner: false,
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: MyHomePage(title: 'Flutter Demo Home Page'),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ MyHomePage({Key key, this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+ int _counter = 0;
+
+ void _incrementCounter() {
+ setState(() {
+ _counter++;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.title),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ Text(
+ 'You have pushed the button this many times:',
+ ),
+ Text(
+ '\$_counter',
+ style: Theme.of(context).textTheme.headline4,
+ ),
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: _incrementCounter,
+ tooltip: 'Increment',
+ child: Icon(Icons.add),
+ ),
+ );
+ }
+}
+''';
+
+// From https://gist.github.com/johnpryan/b3ccb26497ac84895540185935ed5825
+const sampleCodeFlutterSunflower = '''
+import 'package:flutter/material.dart';
+import 'dart:math' as math;
+
+final Color primaryColor = Colors.orange;
+final TargetPlatform platform = TargetPlatform.android;
+
+void main() {
+ runApp(Sunflower());
+}
+
+class SunflowerPainter extends CustomPainter {
+ static const seedRadius = 2.0;
+ static const scaleFactor = 4;
+ static const tau = math.pi * 2;
+
+ static final phi = (math.sqrt(5) + 1) / 2;
+
+ final int seeds;
+
+ SunflowerPainter(this.seeds);
+
+ @override
+ void paint(Canvas canvas, Size size) {
+ var center = size.width / 2;
+
+ for (var i = 0; i < seeds; i++) {
+ var theta = i * tau / phi;
+ var r = math.sqrt(i) * scaleFactor;
+ var x = center + r * math.cos(theta);
+ var y = center - r * math.sin(theta);
+ var offset = Offset(x, y);
+ if (!size.contains(offset)) {
+ continue;
+ }
+ drawSeed(canvas, x, y);
+ }
+ }
+
+ @override
+ bool shouldRepaint(SunflowerPainter oldDelegate) {
+ return oldDelegate.seeds != this.seeds;
+ }
+
+ // Draw a small circle representing a seed centered at (x,y).
+ void drawSeed(Canvas canvas, num x, num y) {
+ var paint = Paint()
+ ..strokeWidth = 2
+ ..style = PaintingStyle.fill
+ ..color = primaryColor;
+ canvas.drawCircle(Offset(x, y), seedRadius, paint);
+ }
+}
+
+class Sunflower extends StatefulWidget {
+ @override
+ State<StatefulWidget> createState() {
+ return _SunflowerState();
+ }
+}
+
+class _SunflowerState extends State<Sunflower> {
+ double seeds = 100.0;
+
+ int get seedCount => seeds.floor();
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ debugShowCheckedModeBanner: false,
+ theme: ThemeData().copyWith(
+ platform: platform,
+ brightness: Brightness.dark,
+ sliderTheme: SliderThemeData.fromPrimaryColors(
+ primaryColor: primaryColor,
+ primaryColorLight: primaryColor,
+ primaryColorDark: primaryColor,
+ valueIndicatorTextStyle: DefaultTextStyle.fallback().style,
+ ),
+ ),
+ home: Scaffold(
+ appBar: AppBar(title: Text("Sunflower")),
+ drawer: Drawer(
+ child: ListView(
+ children: [
+ DrawerHeader(
+ child: Center(
+ child: Container(
+ child: Text(
+ "Sunflower 🌻",
+ style: TextStyle(fontSize: 32),
+ ),
+ ),
+ ),
+ ),
+ ],
+ )),
+ body: Container(
+ constraints: BoxConstraints.expand(),
+ decoration:
+ BoxDecoration(border: Border.all(color: Colors.transparent)),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Container(
+ decoration: BoxDecoration(
+ border: Border.all(color: Colors.transparent)),
+ child: SizedBox(
+ width: 400,
+ height: 400,
+ child: CustomPaint(
+ painter: SunflowerPainter(seedCount),
+ ),
+ ),
+ ),
+ Text("Showing \$seedCount seeds"),
+ ConstrainedBox(
+ constraints: BoxConstraints.tightFor(width: 300),
+ child: Slider.adaptive(
+ min: 20,
+ max: 2000,
+ value: seeds,
+ onChanged: (newValue) {
+ setState(() {
+ seeds = newValue;
+ });
+ },
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
+''';
+
+// From https://gist.github.com/RedBrogdon/ecb28c29c646b7f38139b1e7f44129b7
+const sampleCodeFlutterDraggableCard = '''
+import 'package:flutter/material.dart';
+import 'package:flutter/physics.dart';
+
+main() {
+ runApp(
+ MaterialApp(
+ debugShowCheckedModeBanner: false,
+ home: PhysicsCardDragDemo(),
+ ),
+ );
+}
+
+class PhysicsCardDragDemo extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('A draggable card!'),
+ ),
+ body: DraggableCard(
+ child: FlutterLogo(
+ size: 128,
+ ),
+ ),
+ );
+ }
+}
+
+class DraggableCard extends StatefulWidget {
+ final Widget child;
+ DraggableCard({this.child});
+
+ @override
+ _DraggableCardState createState() => _DraggableCardState();
+}
+
+class _DraggableCardState extends State<DraggableCard>
+ with SingleTickerProviderStateMixin {
+ AnimationController _controller;
+ Alignment _dragAlignment = Alignment.center;
+ Animation<Alignment> _animation;
+
+ void _runAnimation(Offset pixelsPerSecond, Size size) {
+ _animation = _controller.drive(
+ AlignmentTween(
+ begin: _dragAlignment,
+ end: Alignment.center,
+ ),
+ );
+
+ final unitsPerSecondX = pixelsPerSecond.dx / size.width;
+ final unitsPerSecondY = pixelsPerSecond.dy / size.height;
+ final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY);
+ final unitVelocity = unitsPerSecond.distance;
+
+ const spring = SpringDescription(
+ mass: 30,
+ stiffness: 1,
+ damping: 1,
+ );
+
+ final simulation = SpringSimulation(spring, 0, 1, -unitVelocity);
+
+ _controller.animateWith(simulation);
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _controller = AnimationController(vsync: this);
+
+ _controller.addListener(() {
+ setState(() {
+ _dragAlignment = _animation.value;
+ });
+ });
+ }
+
+ @override
+ void dispose() {
+ _controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final size = MediaQuery.of(context).size;
+ return GestureDetector(
+ onPanDown: (details) {
+ _controller.stop();
+ },
+ onPanUpdate: (details) {
+ setState(() {
+ _dragAlignment += Alignment(
+ details.delta.dx / (size.width / 2),
+ details.delta.dy / (size.height / 2),
+ );
+ });
+ },
+ onPanEnd: (details) {
+ _runAnimation(details.velocity.pixelsPerSecond, size);
+ },
+ child: Align(
+ alignment: _dragAlignment,
+ child: Card(
+ child: widget.child,
+ ),
+ ),
+ );
+ }
+}
+''';
+
+// From https://gist.github.com/RedBrogdon/40308e0a5f47acba46ba62f4d8be2bf4
+const sampleCodeFlutterImplicitAnimations = '''
+import 'package:flutter/material.dart';
+import 'dart:math';
+
+class DiscData {
+ static final _rng = Random();
+
+ double size;
+ Color color;
+ Alignment alignment;
+
+ DiscData() {
+ color = Color.fromARGB(
+ _rng.nextInt(200),
+ _rng.nextInt(255),
+ _rng.nextInt(255),
+ _rng.nextInt(255),
+ );
+ size = _rng.nextDouble() * 40 + 10;
+ alignment = Alignment(
+ _rng.nextDouble() * 2 - 1,
+ _rng.nextDouble() * 2 - 1,
+ );
+ }
+}
+
+void main() async {
+ runApp(
+ MaterialApp(
+ debugShowCheckedModeBanner: false,
+ home: Scaffold(
+ body: Container(
+ color: Color(0xFF15202D),
+ child: SizedBox.expand(
+ child: VariousDiscs(50),
+ ),
+ ),
+ ),
+ ),
+ );
+}
+
+class VariousDiscs extends StatefulWidget {
+ final numberOfDiscs;
+
+ VariousDiscs(this.numberOfDiscs);
+
+ @override
+ _VariousDiscsState createState() => _VariousDiscsState();
+}
+
+class _VariousDiscsState extends State<VariousDiscs> {
+ final _discs = <DiscData>[];
+
+ @override
+ void initState() {
+ super.initState();
+ _makeDiscs();
+ }
+
+ void _makeDiscs() {
+ _discs.clear();
+ for (int i = 0; i < widget.numberOfDiscs; i++) {
+ _discs.add(DiscData());
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: () => setState(() {
+ _makeDiscs();
+ }),
+ child: Stack(
+ children: [
+ Center(
+ child: Text(
+ 'Click a disc!',
+ style: TextStyle(color: Colors.white, fontSize: 50),
+ ),
+ ),
+ for (final disc in _discs)
+ Positioned.fill(
+ child: AnimatedAlign(
+ duration: Duration(milliseconds: 500),
+ curve: Curves.easeInOut,
+ alignment: disc.alignment,
+ child: AnimatedContainer(
+ duration: Duration(milliseconds: 500),
+ decoration: BoxDecoration(
+ color: disc.color,
+ shape: BoxShape.circle,
+ ),
+ height: disc.size,
+ width: disc.size,
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+''';
+
const sampleCodeMultiFoo = """
import 'bar.dart';
diff --git a/pubspec.lock b/pubspec.lock
index 52f97c3..41bef28 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -14,7 +14,7 @@
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
- version: "7.0.0"
+ version: "12.0.0"
analysis_server_lib:
dependency: "direct main"
description:
@@ -28,7 +28,7 @@
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
- version: "0.39.17"
+ version: "0.40.6"
appengine:
dependency: "direct main"
description:
@@ -70,14 +70,14 @@
name: build
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0"
+ version: "1.5.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
- version: "0.4.2"
+ version: "0.4.3"
build_daemon:
dependency: transitive
description:
@@ -91,21 +91,21 @@
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.11"
+ version: "1.4.3"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.10.2"
+ version: "1.10.6"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
- version: "6.0.1"
+ version: "6.1.1"
built_collection:
dependency: transitive
description:
@@ -183,20 +183,13 @@
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
- csslib:
- dependency: transitive
- description:
- name: csslib
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.16.2"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.6"
+ version: "1.3.10"
dartis:
dependency: "direct main"
description:
@@ -267,13 +260,6 @@
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.0"
- html:
- dependency: transitive
- description:
- name: html
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.14.0+4"
http:
dependency: "direct main"
description:
@@ -504,7 +490,7 @@
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
- version: "0.9.7+1"
+ version: "0.9.8"
source_map_stack_trace:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 03e8705..7b947a1 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,7 +6,7 @@
sdk: ^2.10.4
dependencies:
- analyzer: ^0.39.17
+ analyzer: ^0.40.6
analysis_server_lib: ^0.1.4
appengine: ^0.12.0
args: ^1.6.0
@@ -26,7 +26,7 @@
dev_dependencies:
async: ^2.2.0
- build_runner: ^1.10.0
+ build_runner: ^1.10.6
codemirror: ^0.5.6
coverage: ^0.14.0
grinder: ^0.8.0
diff --git a/test/compiler_test.dart b/test/compiler_test.dart
index ae09202..8a5cecf 100644
--- a/test/compiler_test.dart
+++ b/test/compiler_test.dart
@@ -36,43 +36,57 @@
expect(result.sourceMap, isNull);
});
- test('compileDDC simple', () async {
- final result = await compiler.compileDDC(sampleCode);
- expect(result.success, true);
- expect(result.compiledJS, isNotEmpty);
- expect(result.modulesBaseUrl, isNotEmpty);
+ Future<void> Function() _generateCompilerDDCTest(String sample) =>
+ () async {
+ final result = await compiler.compileDDC(sample);
+ print(result.problems);
- expect(result.compiledJS, contains("define('dartpad_main', ["));
- });
+ expect(result.success, true);
+ expect(result.compiledJS, isNotEmpty);
+ expect(result.modulesBaseUrl, isNotEmpty);
- test('compileDDC with web', () async {
- final result = await compiler.compileDDC(sampleCodeWeb);
- expect(result.success, true);
- expect(result.compiledJS, isNotEmpty);
- expect(result.modulesBaseUrl, isNotEmpty);
+ expect(result.compiledJS, contains("define('dartpad_main', ["));
+ };
- expect(result.compiledJS, contains("define('dartpad_main', ["));
- });
+ test(
+ 'compileDDC simple',
+ _generateCompilerDDCTest(sampleCode),
+ );
- test('compileDDC with Flutter', () async {
- final result = await compiler.compileDDC(sampleCodeFlutter);
- print(result.problems);
+ test(
+ 'compileDDC with web',
+ _generateCompilerDDCTest(sampleCodeWeb),
+ );
- expect(result.success, true);
- expect(result.compiledJS, isNotEmpty);
- expect(result.modulesBaseUrl, isNotEmpty);
+ test(
+ 'compileDDC with Flutter',
+ _generateCompilerDDCTest(sampleCodeFlutter),
+ );
- expect(result.compiledJS, contains("define('dartpad_main', ["));
- });
+ test(
+ 'compileDDC with Flutter Counter',
+ _generateCompilerDDCTest(sampleCodeFlutterCounter),
+ );
- test('compileDDC with async', () async {
- final result = await compiler.compileDDC(sampleCodeAsync);
- expect(result.success, true);
- expect(result.compiledJS, isNotEmpty);
- expect(result.modulesBaseUrl, isNotEmpty);
+ test(
+ 'compileDDC with Flutter Sunflower',
+ _generateCompilerDDCTest(sampleCodeFlutterSunflower),
+ );
- expect(result.compiledJS, contains("define('dartpad_main', ["));
- });
+ test(
+ 'compileDDC with Flutter Draggable Card',
+ _generateCompilerDDCTest(sampleCodeFlutterDraggableCard),
+ );
+
+ test(
+ 'compileDDC with Flutter Implicit Animations',
+ _generateCompilerDDCTest(sampleCodeFlutterImplicitAnimations),
+ );
+
+ test(
+ 'compileDDC with async',
+ _generateCompilerDDCTest(sampleCodeAsync),
+ );
test('compileDDC with single error', () async {
final result = await compiler.compileDDC(sampleCodeError);