Skip to content
Open
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
4 changes: 4 additions & 0 deletions .github/workflows/native_doc_dartifier.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ jobs:
- uses: subosito/flutter-action@e938fdf56512cc96ef2f93601a5a40bde3801046
with:
channel: ${{ matrix.sdk }}

- name: Download ObjectBox DB .so file
run: bash <(curl -s https://raw.githubusercontent.com/objectbox/objectbox-dart/main/install.sh)

- id: install
name: Install dependencies
run: flutter pub get
Expand Down
51 changes: 51 additions & 0 deletions pkgs/native_doc_dartifier/example/dartify_rag_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2025, 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 'dart:io';

import 'package:native_doc_dartifier/src/context.dart';
import 'package:native_doc_dartifier/src/dartify_code.dart';
import 'package:native_doc_dartifier/src/populate_rag.dart';

void main() async {
const code = '''public void onClick() {
ImageCapture.OutputFileOptions outputFileOptions =
new ImageCapture.OutputFileOptions.Builder(new File("...")).build();
imageCapture.takePicture(outputFileOptions, cameraExecutor,
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
// insert your code here.
}
@Override
public void onError(ImageCaptureException error) {
// insert your code here.
}
}
);
}
''';

final bindingsFile = File('example/camerax.dart');

final bindingsPath = bindingsFile.absolute.path;

// Populate RAG with relevant information from the bindings file
// This step is crucial and must be done only once before using RAG
await populateRAG(Directory.current.path, bindingsPath);

try {
final context = await Context.create(
Directory.current.path,
bindingsPath,
// Indicate that we are using RAG
usingRag: true,
);
final dartCode = await dartifyNativeCode(code, context);
print(dartCode);
} catch (e) {
stderr.writeln('Error: $e');
exit(1);
}
}
5 changes: 0 additions & 5 deletions pkgs/native_doc_dartifier/lib/native_doc_dartifier.dart

This file was deleted.

44 changes: 44 additions & 0 deletions pkgs/native_doc_dartifier/lib/objectbox-model.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
"entities": [
{
"id": "1:7960413809486009791",
"lastPropertyId": "3:8923258437156876593",
"name": "ClassSummaryRAGModel",
"properties": [
{
"id": "1:8829639415366563528",
"name": "id",
"type": 6,
"flags": 1
},
{
"id": "2:3000549143352790148",
"name": "summary",
"type": 9
},
{
"id": "3:8923258437156876593",
"name": "embeddings",
"indexId": "1:6912840214801688687",
"type": 28,
"flags": 8
}
],
"relations": []
}
],
"lastEntityId": "1:7960413809486009791",
"lastIndexId": "1:6912840214801688687",
"lastRelationId": "0:0",
"lastSequenceId": "0:0",
"modelVersion": 5,
"modelVersionParserMinimum": 5,
"retiredEntityUids": [],
"retiredIndexUids": [],
"retiredPropertyUids": [],
"retiredRelationUids": [],
"version": 1
}
157 changes: 157 additions & 0 deletions pkgs/native_doc_dartifier/lib/objectbox.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions pkgs/native_doc_dartifier/lib/src/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,26 @@ class PackageSummary {
}
return buffer.toString();
}

List<String> getRAGSummaries() {
final summaries = <String>[];
final topLevelDeclerations = StringBuffer();

if (packageName.isNotEmpty) {
topLevelDeclerations.writeln('// From: $packageName');
}
for (final function in topLevelFunctions) {
topLevelDeclerations.writeln('$function;');
}
for (final variable in topLevelVariables) {
topLevelDeclerations.writeln('$variable;');
}

summaries.add(topLevelDeclerations.toString());
summaries.addAll(classesSummaries.map((c) => c.toDartLikeRepresentation()));

return summaries;
}
}

class LibraryClassSummary {
Expand Down
48 changes: 32 additions & 16 deletions pkgs/native_doc_dartifier/lib/src/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import 'package:path/path.dart' as p;

import 'ast.dart';
import 'public_abstractor.dart';
import 'rag.dart';

class Context {
late final RAG? rag;
final String projectAbsolutePath;
final String bindingsFileAbsolutePath;
final List<String> importedPackages = [];
Expand All @@ -29,12 +31,14 @@ class Context {

static Future<Context> create(
String projectAbsolutePath,
String bindingsFileAbsolutePath,
) async {
String bindingsFileAbsolutePath, {
bool usingRag = false,
}) async {
final context = Context._(
projectAbsolutePath: projectAbsolutePath,
bindingsFileAbsolutePath: bindingsFileAbsolutePath,
);
context.rag = usingRag ? await RAG.create() : null;
await context._init();
return context;
}
Expand All @@ -46,15 +50,17 @@ class Context {
exit(1);
}

// Get the bindings file summary
final abstractor = PublicAbstractor();
parseString(
content: await bindingsFile.readAsString(),
).unit.visitChildren(abstractor);
bindingsSummary.addAll(abstractor.getBindingsClassesSummary());
if (rag == null) {
// Get the bindings file summary
final abstractor = PublicAbstractor();
parseString(
content: await bindingsFile.readAsString(),
).unit.visitChildren(abstractor);
bindingsSummary.addAll(abstractor.getBindingsClassesSummary());

// Get the packages classes summary, that are imported in the bindings file
await _getLibrariesSummary(projectAbsolutePath, bindingsFileAbsolutePath);
// Get packages classes summary, that are imported in the bindings file
await _getLibrariesSummary(projectAbsolutePath, bindingsFileAbsolutePath);
}
}

Future<void> _getLibrariesSummary(
Expand Down Expand Up @@ -155,14 +161,24 @@ class Context {
return;
}

String toDartLikeRepresentation() {
/// It will return the full context,
/// If [rag] is null or the given [querySnippet] is empty.
Future<String> toDartLikeRepresentation(String querySnippet) async {
final buffer = StringBuffer();
for (final classSummary in bindingsSummary) {
buffer.writeln(classSummary.toDartLikeRepresentation());
}
for (final packageSummary in packageSummaries) {
buffer.writeln(packageSummary.toDartLikeRepresentation());
if (rag != null && querySnippet.isNotEmpty) {
final documents = await rag!.queryRAG(querySnippet);
for (final classSummary in documents) {
buffer.writeln(classSummary);
}
} else {
for (final classSummary in bindingsSummary) {
buffer.writeln(classSummary.toDartLikeRepresentation());
}
for (final packageSummary in packageSummaries) {
buffer.writeln(packageSummary.toDartLikeRepresentation());
}
}

final dartLikeRepresentation = buffer.toString().replaceAll('jni\$_.', '');
return dartLikeRepresentation;
}
Expand Down
2 changes: 1 addition & 1 deletion pkgs/native_doc_dartifier/lib/src/dartify_code.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Future<String> dartifyNativeCode(String sourceCode, Context context) async {

final translatePrompt = TranslatePrompt(
sourceCode,
context.toDartLikeRepresentation(),
await context.toDartLikeRepresentation(sourceCode),
);

final chatSession = model.startChat();
Expand Down
Loading