Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@
# private fields, especially on the Window object):

analyzer:
language:
enableStrictCallChecks: true
enableSuperMixins: true
strong-mode:
implicit-dynamic: false
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
native_function_body_in_non_sdk_code: ignore
# allow having TODOs in the code
todo: ignore
# `flutter analyze` (without `--watch`) just ignores directories
Expand Down Expand Up @@ -94,7 +92,6 @@ linter:
# - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_bool_in_asserts
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally we'd find a way to make this file always exactly the same as the version in the flutter/flutter repo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine a lot of projects would want that functionality -- "start with this canonical analysis options file, then override it with the following options"

Perhaps the analyzer could beef up its include directive to support not only relative paths, but also an enumerated set of SDKs? In this world, we'd move the canonical analysis options that currently live in the flutter repo into the Dart SDK as the "flutter analysis options", then the flutter repo would just say "I use Flutter's options"...

/cc @pq

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat like clang-format use chromium style?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like that too - I usually start a new Flutter project by copying the Flutter repo's analysis_options

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That has landed - pulling it in to this will require a bunch more changes in the implementation files (get rid of optional new, use = instead of : for parameters, etc.) that would be better to do in a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm

Expand Down
8 changes: 1 addition & 7 deletions ci/analyze.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ RESULTS=`dartanalyzer \
--options flutter/analysis_options.yaml \
out/host_debug_unopt/gen/sky/bindings/dart_ui/ui.dart \
2>&1 \
| grep -v "Native functions can only be declared in the SDK and code that is loaded through native extensions" \
| grep -Ev "The function '.+' (is not|isn't) used" \
| grep -Ev "The top level variable '.+' isn't used" \
| grep -Ev "Undefined name 'main'" \
| grep -v "The library 'dart:_internal' is internal" \
| grep -Ev "Unused import.+ui\.dart" \
| grep -Ev "[0-9]+ errors.*found\." \
| grep -Ev "No issues found!" \
| grep -Ev "Analyzing.+out/host_debug_unopt/gen/sky/bindings/dart_ui/ui\.dart"`

echo "$RESULTS"
Expand Down
15 changes: 15 additions & 0 deletions lib/ui/hooks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(dnfield): Remove unused_import ignores when https://github.com/dart-lang/sdk/issues/35164 is resolved.

part of dart.ui;

// ignore: unused_element
String _decodeUTF8(ByteData message) {
return message != null ? utf8.decoder.convert(message.buffer.asUint8List()) : null;
}

// ignore: unused_element
dynamic _decodeJSON(String message) {
return message != null ? json.decode(message) : null;
}

@pragma('vm:entry-point')
// ignore: unused_element
void _updateWindowMetrics(double devicePixelRatio,
double width,
double height,
Expand Down Expand Up @@ -50,9 +55,11 @@ String _localeClosure() {
}

@pragma('vm:entry-point')
// ignore: unused_element
_LocaleClosure _getLocaleClosure() => _localeClosure;

@pragma('vm:entry-point')
// ignore: unused_element
void _updateLocales(List<String> locales) {
const int stringsPerLocale = 4;
final int numLocales = locales.length ~/ stringsPerLocale;
Expand All @@ -71,6 +78,7 @@ void _updateLocales(List<String> locales) {
}

@pragma('vm:entry-point')
// ignore: unused_element
void _updateUserSettingsData(String jsonData) {
final Map<String, dynamic> data = json.decode(jsonData);
if (data.isEmpty) {
Expand All @@ -90,12 +98,14 @@ void _updateAlwaysUse24HourFormat(bool alwaysUse24HourFormat) {
}

@pragma('vm:entry-point')
// ignore: unused_element
void _updateSemanticsEnabled(bool enabled) {
window._semanticsEnabled = enabled;
_invoke(window.onSemanticsEnabledChanged, window._onSemanticsEnabledChangedZone);
}

@pragma('vm:entry-point')
// ignore: unused_element
void _updateAccessibilityFeatures(int values) {
final AccessibilityFeatures newFeatures = new AccessibilityFeatures._(values);
if (newFeatures == window._accessibilityFeatures)
Expand All @@ -122,12 +132,14 @@ void _dispatchPlatformMessage(String name, ByteData data, int responseId) {
}

@pragma('vm:entry-point')
// ignore: unused_element
void _dispatchPointerDataPacket(ByteData packet) {
if (window.onPointerDataPacket != null)
_invoke1<PointerDataPacket>(window.onPointerDataPacket, window._onPointerDataPacketZone, _unpackPointerDataPacket(packet));
}

@pragma('vm:entry-point')
// ignore: unused_element
void _dispatchSemanticsAction(int id, int action, ByteData args) {
_invoke3<int, SemanticsAction, ByteData>(
window.onSemanticsAction,
Expand All @@ -139,11 +151,13 @@ void _dispatchSemanticsAction(int id, int action, ByteData args) {
}

@pragma('vm:entry-point')
// ignore: unused_element
void _beginFrame(int microseconds) {
_invoke1<Duration>(window.onBeginFrame, window._onBeginFrameZone, new Duration(microseconds: microseconds));
}

@pragma('vm:entry-point')
// ignore: unused_element
void _drawFrame() {
_invoke(window.onDrawFrame, window._onDrawFrameZone);
}
Expand Down Expand Up @@ -177,6 +191,7 @@ void _invoke1<A>(void callback(A a), Zone zone, A arg) {
}

/// Invokes [callback] inside the given [zone] passing it [arg1] and [arg2].
// ignore: unused_element
void _invoke2<A1, A2>(void callback(A1 a1, A2 a2), Zone zone, A1 arg1, A2 arg2) {
if (callback == null)
return;
Expand Down
10 changes: 6 additions & 4 deletions lib/ui/natives.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(dnfield): remove unused_element ignores when https://github.com/dart-lang/sdk/issues/35164 is resolved.

part of dart.ui;

// Corelib 'print' implementation.
Expand All @@ -28,7 +30,7 @@ Future<developer.ServiceExtensionResponse> _scheduleFrame(
}

@pragma('vm:entry-point')
void _setupHooks() {
void _setupHooks() { // ignore: unused_element
assert(() {
// In debug mode, register the schedule frame extension.
developer.registerExtension('ext.ui.window.scheduleFrame', _scheduleFrame);
Expand Down Expand Up @@ -67,9 +69,9 @@ int _getCallbackHandle(Function closure) native 'GetCallbackHandle';
Function _getCallbackFromHandle(int handle) native 'GetCallbackFromHandle';

// Required for gen_snapshot to work correctly.
int _isolateId;
int _isolateId; // ignore: unused_element

@pragma('vm:entry-point')
Function _getPrintClosure() => _print;
Function _getPrintClosure() => _print; // ignore: unused_element
@pragma('vm:entry-point')
Function _getScheduleMicrotaskClosure() => _scheduleMicrotask;
Function _getScheduleMicrotaskClosure() => _scheduleMicrotask; // ignore: unused_element
4 changes: 2 additions & 2 deletions lib/ui/ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
/// text, layout, and rendering subsystems.
library dart.ui;

import 'dart:_internal' hide Symbol;
import 'dart:_internal' hide Symbol; // ignore: import_internal_library, unused_import
import 'dart:async';
import 'dart:collection' as collection;
import 'dart:convert';
import 'dart:developer' as developer;
import 'dart:io';
import 'dart:io'; // ignore: unused_import
import 'dart:isolate' show SendPort;
import 'dart:math' as math;
import 'dart:nativewrappers';
Expand Down
2 changes: 1 addition & 1 deletion runtime/fixtures/simple_main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
// found in the LICENSE file.

void main() {
print("Hello");
print('Hello');
}
47 changes: 24 additions & 23 deletions testing/dart/canvas_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,52 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui';
import 'dart:typed_data';
import 'dart:ui';

import 'package:test/test.dart';

typedef void CanvasCallback(Canvas canvas);
typedef CanvasCallback = void Function(Canvas canvas);

void testCanvas(CanvasCallback callback) {
try {
callback(Canvas(PictureRecorder(), Rect.fromLTRB(0.0, 0.0, 0.0, 0.0)));
} catch (error) { }
} catch (error) { } // ignore: empty_catches
}

void main() {
test("canvas APIs should not crash", () {
Paint paint = Paint();
Rect rect = Rect.fromLTRB(double.nan, double.nan, double.nan, double.nan);
RRect rrect = RRect.fromRectAndCorners(rect);
Offset offset = Offset(double.nan, double.nan);
Path path = Path();
Color color = Color(0);
Paragraph paragraph = ParagraphBuilder(ParagraphStyle()).build();
test('canvas APIs should not crash', () {
final Paint paint = Paint();
final Rect rect = Rect.fromLTRB(double.nan, double.nan, double.nan, double.nan);
final RRect rrect = RRect.fromRectAndCorners(rect);
const Offset offset = Offset(double.nan, double.nan);
final Path path = Path();
const Color color = Color(0);
final Paragraph paragraph = ParagraphBuilder(ParagraphStyle()).build();

PictureRecorder recorder = PictureRecorder();
Canvas recorderCanvas = Canvas(recorder);
Picture picture = recorder.endRecording();
Image image = picture.toImage(1, 1);
final PictureRecorder recorder = PictureRecorder();
final Canvas recorderCanvas = Canvas(recorder);
recorderCanvas.scale(1.0, 1.0);
final Picture picture = recorder.endRecording();
final Image image = picture.toImage(1, 1);

try { Canvas(null, null); } catch (error) { }
try { Canvas(null, rect); } catch (error) { }
try { Canvas(PictureRecorder(), null); } catch (error) { }
try { Canvas(PictureRecorder(), rect); } catch (error) { }
try { Canvas(null, null); } catch (error) { } // ignore: empty_catches
try { Canvas(null, rect); } catch (error) { } // ignore: empty_catches
try { Canvas(PictureRecorder(), null); } catch (error) { } // ignore: empty_catches
try { Canvas(PictureRecorder(), rect); } catch (error) { } // ignore: empty_catches

try {
PictureRecorder()
..endRecording()
..endRecording()
..endRecording();
} catch (error) { }
} catch (error) { } // ignore: empty_catches

testCanvas((Canvas canvas) => canvas.clipPath(path));
testCanvas((Canvas canvas) => canvas.clipRect(rect));
testCanvas((Canvas canvas) => canvas.clipRRect(rrect));
testCanvas((Canvas canvas) => canvas.drawArc(rect, 0.0, 0.0, false, paint));
testCanvas((Canvas canvas) => canvas.drawAtlas(image, [], [], [], BlendMode.src, rect, paint));
testCanvas((Canvas canvas) => canvas.drawAtlas(image, <RSTransform>[], <Rect>[], <Color>[], BlendMode.src, rect, paint));
testCanvas((Canvas canvas) => canvas.drawCircle(offset, double.nan, paint));
testCanvas((Canvas canvas) => canvas.drawColor(color, BlendMode.src));
testCanvas((Canvas canvas) => canvas.drawDRRect(rrect, rrect, paint));
Expand All @@ -59,15 +60,15 @@ void main() {
testCanvas((Canvas canvas) => canvas.drawParagraph(paragraph, offset));
testCanvas((Canvas canvas) => canvas.drawPath(path, paint));
testCanvas((Canvas canvas) => canvas.drawPicture(picture));
testCanvas((Canvas canvas) => canvas.drawPoints(PointMode.points, [], paint));
testCanvas((Canvas canvas) => canvas.drawPoints(PointMode.points, <Offset>[], paint));
testCanvas((Canvas canvas) => canvas.drawRawAtlas(image, Float32List(0), Float32List(0), Int32List(0), BlendMode.src, rect, paint));
testCanvas((Canvas canvas) => canvas.drawRawPoints(PointMode.points, Float32List(0), paint));
testCanvas((Canvas canvas) => canvas.drawRect(rect, paint));
testCanvas((Canvas canvas) => canvas.drawRRect(rrect, paint));
testCanvas((Canvas canvas) => canvas.drawShadow(path, color, double.nan, null));
testCanvas((Canvas canvas) => canvas.drawShadow(path, color, double.nan, false));
testCanvas((Canvas canvas) => canvas.drawShadow(path, color, double.nan, true));
testCanvas((Canvas canvas) => canvas.drawVertices(Vertices(VertexMode.triangles, []), null, paint));
testCanvas((Canvas canvas) => canvas.drawVertices(Vertices(VertexMode.triangles, <Offset>[]), null, paint));
testCanvas((Canvas canvas) => canvas.getSaveCount());
testCanvas((Canvas canvas) => canvas.restore());
testCanvas((Canvas canvas) => canvas.rotate(double.nan));
Expand Down
Loading