Skip to content

Use DiagnosticableMixin instead of Diagnosticable for some conditionals.#49726

Merged
gspencergoog merged 2 commits intoflutter:masterfrom
gspencergoog:fix_diagnosticable
Jan 30, 2020
Merged

Use DiagnosticableMixin instead of Diagnosticable for some conditionals.#49726
gspencergoog merged 2 commits intoflutter:masterfrom
gspencergoog:fix_diagnosticable

Conversation

@gspencergoog
Copy link
Copy Markdown
Contributor

@gspencergoog gspencergoog commented Jan 29, 2020

Description

As the code is right now, if you try and print diagnostics for a Shortcuts widget that has a manager set (a ShortcutManager), it will fail at runtime. This code:

import 'package:flutter/widgets.dart';

void main() {
  try {
    print(Shortcuts(shortcuts: {}, manager: ShortcutManager()));
  } catch (ex, stack) {
    print(ex);
    print(stack);
  }
}

will fail with this exception:

flutter: type 'ShortcutManager' is not a subtype of type 'Diagnosticable' in type cast
flutter: #0      DiagnosticableMixin.toDiagnosticsNode (package:flutter/src/foundation/diagnostics.dart:3113:19)
#1      DiagnosticableMixin.toString.<anonymous closure> (package:flutter/src/foundation/diagnostics.dart:3095:20)
#2      DiagnosticableMixin.toString (package:flutter/src/foundation/diagnostics.dart:3097:6)
#3      DiagnosticsProperty.valueToString (package:flutter/src/foundation/diagnostics.dart:2698:61)
#4      DiagnosticsProperty.toDescription (package:flutter/src/foundation/diagnostics.dart:2712:21)
#5      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1169:31)
#6      TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1279:39)
#7      DiagnosticsNode.toStringDeep (package:flutter/src/foundation/diagnostics.dart:1709:7)
#8      DiagnosticsNode.toString (package:flutter/src/foundation/diagnostics.dart:1631:14)
#9      DiagnosticableMixin.toString.<anonymous closure> (package:flutter/src/foundation/diagnostics.dart:3095:78)
#10     DiagnosticableMixin.toString (package:flutter/src/foundation/diagnostics.dart:3097:6)
#11     _StringBase._interpolateSingle (dart:core-patch/string_patch.dart:823:17)
#12     print (dart:core/print.dart:11:26)
#13     main (package:focus_samples/focus_traversal_group.dart:5:5)
...

The reasons for this are explained in #49647 (comment)

This PR fixes this by changing DiagnosticableMixin.toDiagnosticsNode and other things to accept DiagnosticableMixin instead of requiring Diagnosticable.

Eventually, after making some changes to the linter and some other external repos, we can deprecate and them remove Diagnosticable entirely and just have the mixin.

Related Issues

Tests

  • Updated diagnostics_test.dart, although no functionality changed.

Breaking Change

  • No, this is not a breaking change.

@fluttergithubbot fluttergithubbot added a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Jan 29, 2020
@gspencergoog
Copy link
Copy Markdown
Contributor Author

gspencergoog commented Jan 29, 2020

Actually, after doing the "full" fix here, it occurred to me that there is a simpler fix to the original problem, although it still doesn't fix the structural issues with the way Diagnosticable is set up.

We can just change DiagnosticableNode to be:

class DiagnosticableNode<T extends DiagnosticableMixin> extends DiagnosticsNode {

and change DiagnosticableMixin.toDiagnosticsNode to use DiagnosticableMixin instead:

  DiagnosticsNode toDiagnosticsNode({ String name, DiagnosticsTreeStyle style }) {
    return DiagnosticableNode<DiagnosticableMixin>(
      name: name,
      value: this,
      style: style,
    );
  }

That wouldn't be a breaking change, and nothing gets deprecated. It does leave a pitfall for people that use is Diagnosticable instead of is DiagnosticableMixin, so it's not as desirable in that sense.

Copy link
Copy Markdown
Contributor

@ds84182 ds84182 left a comment

Choose a reason for hiding this comment

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

LGTM

Later on, would it be useful to switch the names? With generalized typedefs I think you'd be able to do

mixin Diagnosticable {...}

@Deprecated(...)
typedef DiagnosticableMixin = Diagnosticable;

to move everyone over to the new name.

@gspencergoog
Copy link
Copy Markdown
Contributor Author

gspencergoog commented Jan 29, 2020

I don't think I'd switch the names back, simply because Flutter has a convention of naming mixins with the suffix "Mixin", and mixin Diagnosticable wouldn't follow that convention.

What would you think of me doing the simpler change I mentioned in #49726 (comment)?

@ds84182
Copy link
Copy Markdown
Contributor

ds84182 commented Jan 29, 2020 via email

@gspencergoog
Copy link
Copy Markdown
Contributor Author

gspencergoog commented Jan 29, 2020

OK, I think deprecating and removing Diagnosticable is the right change eventually, but in order to be able to put in preemptive changes to other repos to make the transition smoother, I think I'll do the simpler fix first, and then convert other repos to use DiagnosticableMixin ahead of this change that switches all widgets to not be Diagnosticable, because any checks for is Diagnosticable would fail.

Things like the dart linter will stop reporting lints for diagnostic_describe_all_properties on classes that switch to the mixin, and the dart devtools needs changes too. If I don't make the fix first, then it would break things to switch non-Flutter-repo classes to use the mixin instead of extending Diagnosticable. They would fail in the same way as ShortcutManager when they tried to be converted to a DiagnosticNode.

Once I commit the simple fix, then I can switch other classes without any breakage, so that when I commit a change that changes the type of the widgets, nothing will stop working.

I've reverted the changes that switch widgets to use the mixin, and added implements Diagnosticable to those few classes that were just using the mixin, as well as switching anything that was testing is Diagnosticable or template args that assert <T extends Diagnosticable> to use the mixin instead, since that only broadens the match.

@gspencergoog gspencergoog changed the title Move everything over to use DiagnosticableMixin instead of Diagnosticable, and deprecate Diagnosticable Use DiagnosticableMixin instead of Diagnosticable Jan 29, 2020
@gspencergoog gspencergoog changed the title Use DiagnosticableMixin instead of Diagnosticable Use DiagnosticableMixin instead of Diagnosticable for some conditionals. Jan 29, 2020
@lock
Copy link
Copy Markdown

lock Bot commented Apr 2, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@lock lock Bot locked and limited conversation to collaborators Apr 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

extends Diagnosticable != with DiagnosticableMixin

4 participants