Skip to content

feat(cli): UTExportedTypeDeclarations support for file associations#25

Open
hila-f-qodo wants to merge 2 commits intodevin_pr_code_review_bench_100_devin2_base_featcli_utexportedtypedeclarations_support_for_file_associations_pr166from
devin_pr_code_review_bench_100_devin2_head_featcli_utexportedtypedeclarations_support_for_file_associations_pr166
Open

feat(cli): UTExportedTypeDeclarations support for file associations#25
hila-f-qodo wants to merge 2 commits intodevin_pr_code_review_bench_100_devin2_base_featcli_utexportedtypedeclarations_support_for_file_associations_pr166from
devin_pr_code_review_bench_100_devin2_head_featcli_utexportedtypedeclarations_support_for_file_associations_pr166

Conversation

@hila-f-qodo
Copy link
Copy Markdown

@hila-f-qodo hila-f-qodo commented Jan 26, 2026

Benchmark PR from qodo-benchmark#166


Open with Devin

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

View issues and 3 additional flags in Devin Review.

Open in Devin Review

Comment on lines +328 to +338
if association.ext.is_empty() {
dict.insert(
"CFBundleTypeExtensions".into(),
plist::Value::Array(
association
.ext
.iter()
.map(|ext| ext.to_string().into())
.collect(),
),
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Inverted condition causes CFBundleTypeExtensions to be inserted only when ext is empty

The condition on line 328 is inverted. It inserts CFBundleTypeExtensions only when association.ext.is_empty(), which will always result in an empty array being inserted.

Click to expand

Actual behavior

The code:

if association.ext.is_empty() {
  dict.insert(
    "CFBundleTypeExtensions".into(),
    plist::Value::Array(
      association.ext.iter().map(|ext| ext.to_string().into()).collect(),
    ),
  );
}

This only inserts CFBundleTypeExtensions when ext is empty, resulting in an empty array.

Expected behavior

The condition should be if !association.ext.is_empty() to insert extensions when they exist.

Impact

File associations with extensions (the common case) will not have their extensions registered in the Info.plist, breaking macOS file type associations.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 350 to 355
association
.name
.as_ref()
.unwrap_or(&association.ext[0].0)
.expect("File association must have a name")
.to_string()
.into(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Panic when FileAssociation.name is None due to removed fallback

The code uses .expect() on association.name which is an Option<String>, causing a panic when name is not provided.

Click to expand

Actual behavior

The new code:

association
  .name
  .as_ref()
  .expect("File association must have a name")

This panics when name is None.

Expected behavior

The old code had a fallback to use the first extension as the name:

.unwrap_or(&association.ext[0].0)

Impact

The example config at examples/file-associations/src-tauri/tauri.conf.json has file associations without name fields (e.g., the png, jpg, gif associations), which will cause a panic at bundle time on macOS.

Recommendation: Restore the fallback: .unwrap_or(&association.ext[0].0) or use .unwrap_or_else(|| &association.ext.first().map(|e| &e.0).unwrap_or(&"Unknown".to_string()))

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +284 to +289
if let Some(content_types) = &association.content_types {
dict.insert(
"UTTypeConformsTo".into(),
plist::Value::Array(content_types.iter().map(|s| s.clone().into()).collect()),
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 UTTypeConformsTo uses wrong source field (content_types instead of exported_type.conforms_to)

When building UTExportedTypeDeclarations, the code incorrectly uses association.content_types for UTTypeConformsTo instead of exported_type.conforms_to.

Click to expand

Actual behavior

The code at lines 284-289:

if let Some(content_types) = &association.content_types {
  dict.insert(
    "UTTypeConformsTo".into(),
    plist::Value::Array(content_types.iter().map(|s| s.clone().into()).collect()),
  );
}

This uses association.content_types which is meant for LSItemContentTypes in CFBundleDocumentTypes.

Expected behavior

Should use exported_type.conforms_to as defined in ExportedFileAssociation struct at crates/tauri-utils/src/config.rs:1215-1216:

pub conforms_to: Option<Vec<String>>,

Impact

The conformsTo field in the config (e.g., ["public.json"] in the example) will not be used for UTTypeConformsTo, breaking custom type declarations that need to specify their conformance hierarchy.

Recommendation: Change to use exported_type.conforms_to instead of association.content_types

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants