-
Notifications
You must be signed in to change notification settings - Fork 365
Connect the Property Editor to DTD #8598
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
579eab9
Working
elliette def221a
show method if no editable arguments
elliette 48704eb
Clean up
elliette 9942af6
Clean up and update tests
elliette c6734d4
Rename
elliette d92672c
Respond to PR comments
elliette 5306011
Merge branch 'master' into connect-to-dtd
elliette 359f098
Clean up after merge
elliette 0be5cf4
Respond to PR comments
elliette File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ import 'package:devtools_shared/devtools_shared.dart'; | |
|
|
||
| const editorServiceName = 'Editor'; | ||
| const editorStreamName = 'Editor'; | ||
| const lspServiceName = 'Lsp'; | ||
|
|
||
| enum EditorMethod { | ||
| // Device. | ||
|
|
@@ -20,6 +21,22 @@ enum EditorMethod { | |
| openDevToolsPage, | ||
| } | ||
|
|
||
| /// Method names of LSP requests registered on the Analysis Server. | ||
| /// | ||
| /// These should be kept in sync with the methods defined at | ||
| /// [pkg/analysis_server/lib/src/lsp/constants.dart][code link] | ||
| /// | ||
| /// [code link]: https://github.com/dart-lang/sdk/blob/ebfcd436da65802a2b20d415afe600b51e432305/pkg/analysis_server/lib/src/lsp/constants.dart#L136 | ||
| enum LspMethod { | ||
elliette marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| editableArguments( | ||
| methodName: 'experimental/dart/textDocument/editableArguments', | ||
| ); | ||
|
|
||
| const LspMethod({required this.methodName}); | ||
|
|
||
| final String methodName; | ||
| } | ||
|
|
||
| /// Known kinds of events that may come from the editor. | ||
| /// | ||
| /// This list is not guaranteed to match actual events from any given editor as | ||
|
|
@@ -53,41 +70,64 @@ enum EditorEventKind { | |
|
|
||
| /// The kind for a [ThemeChangedEvent]. | ||
| themeChanged, | ||
|
|
||
| /// The kind for an [ActiveLocationChangedEvent] event. | ||
| activeLocationChanged, | ||
| } | ||
|
|
||
| /// Constants for all fields used in JSON maps to avoid literal strings that | ||
| /// may have typos sprinkled throughout the API classes. | ||
| abstract class Field { | ||
| static const active = 'active'; | ||
| static const anchor = 'anchor'; | ||
| static const arguments = 'arguments'; | ||
| static const backgroundColor = 'backgroundColor'; | ||
| static const category = 'category'; | ||
| static const character = 'character'; | ||
| static const debuggerType = 'debuggerType'; | ||
| static const debugSession = 'debugSession'; | ||
| static const debugSessionId = 'debugSessionId'; | ||
| static const debugSessions = 'debugSessions'; | ||
| static const device = 'device'; | ||
| static const deviceId = 'deviceId'; | ||
| static const devices = 'devices'; | ||
| static const displayValue = 'displayValue'; | ||
| static const emulator = 'emulator'; | ||
| static const emulatorId = 'emulatorId'; | ||
| static const ephemeral = 'ephemeral'; | ||
| static const errorText = 'errorText'; | ||
| static const flutterDeviceId = 'flutterDeviceId'; | ||
| static const flutterMode = 'flutterMode'; | ||
| static const fontSize = 'fontSize'; | ||
| static const forceExternal = 'forceExternal'; | ||
| static const foregroundColor = 'foregroundColor'; | ||
| static const hasArgument = 'hasArgument'; | ||
| static const id = 'id'; | ||
| static const isDarkMode = 'isDarkMode'; | ||
| static const isDefault = 'isDefault'; | ||
| static const isEditable = 'isEditable'; | ||
| static const isNullable = 'isNullable'; | ||
| static const isRequired = 'isRequired'; | ||
| static const line = 'line'; | ||
| static const name = 'name'; | ||
| static const options = 'options'; | ||
| static const page = 'page'; | ||
| static const platform = 'platform'; | ||
| static const platformType = 'platformType'; | ||
| static const prefersDebugSession = 'prefersDebugSession'; | ||
| static const projectRootPath = 'projectRootPath'; | ||
| static const requiresDebugSession = 'requiresDebugSession'; | ||
| static const result = 'result'; | ||
| static const selectedDeviceId = 'selectedDeviceId'; | ||
| static const selections = 'selections'; | ||
| static const supported = 'supported'; | ||
| static const supportsForceExternal = 'supportsForceExternal'; | ||
| static const textDocument = 'textDocument'; | ||
| static const theme = 'theme'; | ||
| static const type = 'type'; | ||
| static const uri = 'uri'; | ||
| static const value = 'value'; | ||
| static const version = 'version'; | ||
| static const vmServiceUri = 'vmServiceUri'; | ||
| } | ||
|
|
||
|
|
@@ -256,6 +296,243 @@ class ThemeChangedEvent extends EditorEvent { | |
| Map<String, Object?> toJson() => {Field.theme: theme}; | ||
| } | ||
|
|
||
| /// An event sent by an editor when the current cursor position/s change. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: "cursor position changes" ?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was trying to specify that this could be either a single or multiple cursor positions. |
||
| class ActiveLocationChangedEvent extends EditorEvent { | ||
| ActiveLocationChangedEvent({ | ||
| required this.selections, | ||
| required this.textDocument, | ||
| }); | ||
|
|
||
| ActiveLocationChangedEvent.fromJson(Map<String, Object?> map) | ||
| : this( | ||
| textDocument: TextDocument.fromJson( | ||
| map[Field.textDocument] as Map<String, Object?>, | ||
| ), | ||
| selections: | ||
| (map[Field.selections] as List<Object?>) | ||
| .cast<Map<String, Object?>>() | ||
| .map(EditorSelection.fromJson) | ||
| .toList(), | ||
| ); | ||
|
|
||
| final List<EditorSelection> selections; | ||
| final TextDocument textDocument; | ||
|
|
||
| @override | ||
| EditorEventKind get kind => EditorEventKind.activeLocationChanged; | ||
|
|
||
| @override | ||
| Map<String, Object?> toJson() => { | ||
| Field.selections: selections, | ||
| Field.textDocument: textDocument, | ||
| }; | ||
| } | ||
|
|
||
| /// A reference to a text document in the editor. | ||
| /// | ||
| /// The [uriAsString] is a file URI to the text document. | ||
| /// | ||
| /// The [version] is an integer corresponding to LSP's | ||
| /// [VersionedTextDocumentIdentifier](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#versionedTextDocumentIdentifier) | ||
| class TextDocument with Serializable { | ||
| TextDocument({required this.uriAsString, required this.version}); | ||
|
|
||
| TextDocument.fromJson(Map<String, Object?> map) | ||
| : this( | ||
| uriAsString: map[Field.uri] as String, | ||
| version: map[Field.version] as int, | ||
| ); | ||
|
|
||
| final String uriAsString; | ||
| final int version; | ||
|
|
||
| @override | ||
| Map<String, Object?> toJson() => { | ||
| Field.uri: uriAsString, | ||
| Field.version: version, | ||
| }; | ||
|
|
||
| @override | ||
| bool operator ==(Object other) { | ||
| return other is TextDocument && | ||
| other.uriAsString == uriAsString && | ||
| other.version == version; | ||
| } | ||
|
|
||
| @override | ||
| int get hashCode => Object.hash(uriAsString, version); | ||
| } | ||
|
|
||
| /// The starting and ending cursor positions in the editor. | ||
| class EditorSelection with Serializable { | ||
| EditorSelection({required this.active, required this.anchor}); | ||
|
|
||
| EditorSelection.fromJson(Map<String, Object?> map) | ||
| : this( | ||
| active: CursorPosition.fromJson( | ||
| map[Field.active] as Map<String, Object?>, | ||
| ), | ||
| anchor: CursorPosition.fromJson( | ||
| map[Field.anchor] as Map<String, Object?>, | ||
| ), | ||
| ); | ||
|
|
||
| final CursorPosition active; | ||
| final CursorPosition anchor; | ||
|
|
||
| @override | ||
| Map<String, Object?> toJson() => { | ||
| Field.active: active.toJson(), | ||
| Field.anchor: anchor.toJson(), | ||
| }; | ||
| } | ||
|
|
||
| /// Representation of a single cursor position in the editor. | ||
| /// | ||
| /// The cursor position is after the given [character] of the [line]. | ||
| class CursorPosition with Serializable { | ||
| CursorPosition({required this.character, required this.line}); | ||
|
|
||
| CursorPosition.fromJson(Map<String, Object?> map) | ||
| : this( | ||
| character: map[Field.character] as int, | ||
| line: map[Field.line] as int, | ||
| ); | ||
|
|
||
| /// The zero-based character number of this position. | ||
| final int character; | ||
elliette marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /// The zero-based line number of this position. | ||
| final int line; | ||
elliette marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @override | ||
| Map<String, Object?> toJson() => { | ||
| Field.character: character, | ||
| Field.line: line, | ||
| }; | ||
|
|
||
| @override | ||
| bool operator ==(Object other) { | ||
| return other is CursorPosition && | ||
| other.character == character && | ||
| other.line == line; | ||
| } | ||
|
|
||
| @override | ||
| int get hashCode => Object.hash(character, line); | ||
| } | ||
|
|
||
| /// The result of an `editableArguments` request. | ||
| class EditableArgumentsResult with Serializable { | ||
| EditableArgumentsResult({required this.args}); | ||
|
|
||
| EditableArgumentsResult.fromJson(Map<String, Object?> map) | ||
| : this( | ||
| args: | ||
| (map[Field.arguments] as List<Object?>? ?? <Object?>[]) | ||
| .cast<Map<String, Object?>>() | ||
| .map(EditableArgument.fromJson) | ||
| .toList(), | ||
| ); | ||
|
|
||
| final List<EditableArgument> args; | ||
|
|
||
| @override | ||
| Map<String, Object?> toJson() => {Field.arguments: args}; | ||
| } | ||
|
|
||
| /// Information about a single editable argument of a widget. | ||
| class EditableArgument with Serializable { | ||
| EditableArgument({ | ||
| required this.name, | ||
| required this.type, | ||
| required this.value, | ||
| required this.hasArgument, | ||
| required this.isDefault, | ||
| required this.isNullable, | ||
| required this.isRequired, | ||
| required this.isEditable, | ||
| this.options, | ||
| this.displayValue, | ||
| this.errorText, | ||
| }); | ||
|
|
||
| EditableArgument.fromJson(Map<String, Object?> map) | ||
| : this( | ||
| name: map[Field.name] as String, | ||
| type: map[Field.type] as String, | ||
| value: map[Field.value], | ||
| hasArgument: (map[Field.hasArgument] as bool?) ?? false, | ||
| isDefault: (map[Field.isDefault] as bool?) ?? false, | ||
| isNullable: (map[Field.isNullable] as bool?) ?? false, | ||
| isRequired: (map[Field.isRequired] as bool?) ?? false, | ||
| isEditable: (map[Field.isEditable] as bool?) ?? true, | ||
| options: (map[Field.options] as List<Object?>?)?.cast<String>(), | ||
| displayValue: map[Field.displayValue] as String?, | ||
| errorText: map[Field.errorText] as String?, | ||
| ); | ||
|
|
||
| /// The name of the corresponding parameter. | ||
| final String name; | ||
|
|
||
| /// The type of the corresponding parameter. | ||
| /// | ||
| /// This is not necessarily the Dart type, it is from a defined set of values | ||
| /// that clients may understand how to edit. | ||
| final String type; | ||
|
|
||
| /// The current value for this argument. | ||
| final Object? value; | ||
|
|
||
| /// Whether an explicit argument exists for this parameter in the code. | ||
| final bool hasArgument; | ||
|
|
||
| /// Whether the value is the default for this parameter. | ||
| final bool isDefault; | ||
|
|
||
| /// Whether this argument can be `null`. | ||
| final bool isNullable; | ||
|
|
||
| /// Whether this argument is required. | ||
| final bool isRequired; | ||
|
|
||
| /// Whether this argument can be edited by the Analysis Server. | ||
| /// | ||
| /// An argument might not be editable, e.g. if it is a positional parameter | ||
| /// where previous positional parameters have no argument. | ||
| final bool isEditable; | ||
|
|
||
| /// A list of values that could be provided for this argument. | ||
| /// | ||
| /// This will only be included if the parameter's [type] is "enum". | ||
| final List<String>? options; | ||
|
|
||
| /// A string that can be displayed to indicate the value for this argument. | ||
| /// | ||
| /// This is populated in cases where the source code is not literally the same | ||
| /// as the value field, for example an expression or named constant. | ||
| final String? displayValue; | ||
|
|
||
| final String? errorText; | ||
|
|
||
| String get valueDisplay => displayValue ?? value.toString(); | ||
|
|
||
| @override | ||
| Map<String, Object?> toJson() => { | ||
| Field.name: name, | ||
| Field.type: type, | ||
| Field.value: value, | ||
| Field.hasArgument: hasArgument, | ||
| Field.isDefault: isDefault, | ||
| Field.isNullable: isNullable, | ||
| Field.isRequired: isRequired, | ||
| Field.isEditable: isEditable, | ||
| Field.options: options, | ||
| Field.displayValue: displayValue, | ||
| Field.errorText: errorText, | ||
| }; | ||
| } | ||
|
|
||
| /// The result of a `GetDevices` request. | ||
| class GetDevicesResult with Serializable { | ||
| GetDevicesResult({required this.devices, required this.selectedDeviceId}); | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.