Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions pkgs/jnigen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
elements.dart is no longer exported from the library, as these classes were
always intended to be private. `Config.importedClasses` and
`Config.importClasses()` have also been made private.
- Preserve Java `@deprecated` Javadoc messages in generated Dart
`@Deprecated` annotations.
- Support versions 3.x of `package:package_config`.

## 0.16.0
Expand Down
4 changes: 3 additions & 1 deletion pkgs/jnigen/lib/src/bindings/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1312,7 +1312,9 @@ ${modifier}final _$idName = $_protectedExtension
}
final params = defArgs.delimited(', ');
if (node.isDeprecated) {
s.writeln(" @core\$_.Deprecated('This Java method is deprecated.')");
final message = node.javadoc?.deprecatedMessage ??
"'This Java method is deprecated.'";
s.writeln(' @core\$_.Deprecated($message)');
}
if (node.methodKind == MethodKind.getter) {
s.write(' $ifStatic$returnType get $name ');
Expand Down
44 changes: 44 additions & 0 deletions pkgs/jnigen/lib/src/elements/elements.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:convert';

import 'package:json_annotation/json_annotation.dart';
import 'package:meta/meta.dart';

Expand Down Expand Up @@ -973,6 +975,48 @@ class JavaDocComment implements Element<JavaDocComment> {

final String comment;

String? get deprecatedMessage {
final lines = comment.split('\n');
final messageLines = <String>[];
var readingDeprecatedTag = false;

for (final line in lines) {
final trimmed = line.trim();

if (!readingDeprecatedTag) {
if (trimmed.startsWith('@deprecated')) {
readingDeprecatedTag = true;

final firstLine = trimmed.substring('@deprecated'.length).trim();
if (firstLine.isNotEmpty) {
messageLines.add(firstLine);
}
}
continue;
}

// A new Javadoc block tag marks the end of the deprecated message.
if (trimmed.startsWith('@')) {
break;
}

if (trimmed.isNotEmpty) {
messageLines.add(trimmed);
}
}

final message = messageLines.join('\n').trim();
if (message.isEmpty) return null;

final encoded = jsonEncode(message);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should probably roll our own Dart string escaper, rather than relying on this JSON encoding trick. It's sort of a coincidence that JSON uses mostly the same escape characters as Dart. In fact there are some small differences in the escaping rules that are leading to test failures like this. It'd be better to write (and unit test) a dedicated function for this.

You may also need to regenerate the bindings for that test, to fix this failure. Try tool/regenerate_all_bindings.dart. That tool can be a bit problematic to run, so let me know if you have issues with it (eg errors, or spurious diffs) and I can regerenate the bindings for you on my machine.

final contents = encoded
.substring(1, encoded.length - 1)
.replaceAll("'", r"\'")
.replaceAll(r'$', r'\$');

return "'$contents'";
}

factory JavaDocComment.fromJson(Map<String, dynamic> json) =>
_$JavaDocCommentFromJson(json);

Expand Down
114 changes: 114 additions & 0 deletions pkgs/jnigen/test/deprecated_message_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:jnigen/src/elements/elements.dart';
import 'package:test/test.dart';

void main() {
group('JavaDocComment.deprecatedMessage', () {
test('extracts a single-line message', () {
final comment = JavaDocComment(
comment: '@deprecated Use the replacement method instead.',
);

expect(
comment.deprecatedMessage,
"'Use the replacement method instead.'",
);
});

test('allows description text before the tag', () {
final comment = JavaDocComment(
comment: '''
This method is retained for compatibility.

@deprecated Use the replacement method instead.
''',
);

expect(
comment.deprecatedMessage,
"'Use the replacement method instead.'",
);
});

test('extracts a multiline message', () {
final comment = JavaDocComment(
comment: '''
@deprecated Use the replacement method instead.
This method will be removed in a future release.
''',
);

expect(
comment.deprecatedMessage,
r"'Use the replacement method instead.\nThis method will be removed in a future release.'",
);
});

test('stops at the next block tag', () {
final comment = JavaDocComment(
comment: '''
@deprecated Use the replacement method instead.
This method will be removed soon.
@return the old result
''',
);

expect(
comment.deprecatedMessage,
r"'Use the replacement method instead.\nThis method will be removed soon.'",
);
});

test('returns null when the tag is absent', () {
final comment = JavaDocComment(
comment: 'This is a regular Javadoc comment.',
);

expect(comment.deprecatedMessage, isNull);
});

test('returns null when the message is empty', () {
final comment = JavaDocComment(
comment: '@deprecated',
);

expect(comment.deprecatedMessage, isNull);
});

test('escapes apostrophes and dollar signs', () {
final comment = JavaDocComment(
comment: r"@deprecated Don't use $oldMethod.",
);

expect(
comment.deprecatedMessage,
r"'Don\'t use \$oldMethod.'",
);
});

test('escapes backslashes', () {
final comment = JavaDocComment(
comment: r'@deprecated Use C:\temp instead.',
);

expect(
comment.deprecatedMessage,
r"'Use C:\\temp instead.'",
);
});

test('escapes double quotes', () {
final comment = JavaDocComment(
comment: '@deprecated Use "newMethod" instead.',
);

expect(
comment.deprecatedMessage,
"'Use \\\"newMethod\\\" instead.'",
);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ public String joinStrings(List<String> values, String delim) {
return null;
}

/**
* This method is retained for compatibility.
*
* @deprecated Use methodWithSeveralParams instead.
*/
@Deprecated
public String deprecatedMethod() {
return "deprecated";
Expand Down
Loading