This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Refactor host::OpenFileInExternalEditor
ClosedPublic

Authored by JDevlieghere on Apr 28 2023, 10:49 AM.

Details

Summary

This patch refactors the macOS implementation of OpenFileInExternalEditor:

  • Fix AppleEvent memory leak
  • Fix caching of LLDB_EXTERNAL_EDITOR
  • Fix (speculatively) crash when CFURL is NULL.
  • Improve readability
  • Improve documentation
  • Improve logging

rdar://108633464

PS: A bunch of the Launch Services APIs have been deprecated (LSFindApplicationForInfo, LSOpenURLsWithRole). The preferred API is LSOpenCFURLRef but it doesn't allow you to specify the "location" Apple Event which is used to highlight the current line. Interestingly enough, both Xcode (the default) and TextEdit both ignore that. Sublime Text on the other hand does honor it. Since the old APIs are deprecated but still available, I prefer not to regress the current functionality.

Diff Detail

Event Timeline

JDevlieghere created this revision.Apr 28 2023, 10:49 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 28 2023, 10:49 AM
JDevlieghere requested review of this revision.Apr 28 2023, 10:49 AM
JDevlieghere edited the summary of this revision. (Show Details)Apr 28 2023, 10:54 AM

LGTM overall. A few nits but overall an excellent cleanup! :)

lldb/source/Host/macosx/objcxx/Host.mm
337

nit: Move log line below checking if the file_path is empty? If the file_spec is empty we may see strange log lines like "Sending :0 to external editor" which is just noise.

343–344

Could you document what the NULL and false refer to? I think they're for allocator and isDirectory or something like that.

419–420

I know you're preserving existing behavior here (or rather, fixing its faulty implementation), but I think it would be nice if you didn't have to restart your session and add an environment variable to get this working with an existing debug session. Or maybe make it a setting?

425–427

Should we exit early if we don't have g_app_fsref filled in? The application field of app_params won't be filled in so what will LSOpenURLsWithRole do?

mib accepted this revision.Apr 28 2023, 11:05 AM

LGTM with some comments

lldb/source/Host/macosx/objcxx/Host.mm
335

I guess this doesn't need to be a const std::string, a llvm::StringRef would have been nice but looking at SBFileSpec::GetPath, there is unfortunately no overload for that.

417–418

why is this static ?

This revision is now accepted and ready to land.Apr 28 2023, 11:05 AM
JDevlieghere marked 3 inline comments as done.Apr 28 2023, 11:09 AM
JDevlieghere added inline comments.
lldb/source/Host/macosx/objcxx/Host.mm
337

I actually did that on purpose, so we could tell from the logs that it's empty. It didn't seem worth adding a whole separate log line for, but if you think :10 looks weird, I'm happy to do it.

419–420

I think we're trying to mimic the EDITOR and VISUAL environment variables but I agree a setting would be better. I can add that in a follow-up. Which one should take preference if you have both?

425–427

No, the application is optional. If none is specified we use the default. You can't pass a default constructor one though, it has to be NULL, which is why we have the check here.

JDevlieghere marked 5 inline comments as done.Apr 28 2023, 11:11 AM
JDevlieghere added inline comments.
lldb/source/Host/macosx/objcxx/Host.mm
335

Given how FileSpecs stores path components, you basically always need an owning string.

417–418

Because it is cached across calls.

mib added inline comments.Apr 28 2023, 11:12 AM
lldb/source/Host/macosx/objcxx/Host.mm
343–344

+1

425–427

Looking at the documentation (https://developer.apple.com/documentation/coreservices/1448184-lsopenurlswithrole), if app_params.application is NULL, LSOpenURLsWithRole makes use of kLSRolesAll (https://developer.apple.com/documentation/coreservices/lsrolesmask?language=objc) which I believe open the default application for that file.

mib added inline comments.Apr 28 2023, 11:13 AM
lldb/source/Host/macosx/objcxx/Host.mm
433
jingham added inline comments.
lldb/source/Host/macosx/objcxx/Host.mm
425–427

LSOpenURLsWithRole will use the default application for the extension that the file path we pass it has, however, that's likely to be a different app than the one the user dialed up with LLDB_EXTERNAL_EDITOR.

If the user told us to use an external editor at some path, but we can't actually find that application, then letting the default application open seems wrong. Ideally, we would raise an error saying "External Editor: ... not found" but it doesn't look like there's any way to report errors from this code.

bulbazord added inline comments.Apr 28 2023, 11:16 AM
lldb/source/Host/macosx/objcxx/Host.mm
337

I think a separate log line would be easier to read for somebody not familiar with this codepath. It would be confusing otherwise. Something like "OpenFileInExternalEditor called with empty path"? Or maybe you can keep the log line but change it to:

LLDB_LOG(log, "Sending {0}:{1} to external editor", file_path.empty() ? "<invalid>" : file_path, line_no);
419–420

I would say a setting should probably take priority? That way you can change it during your session if desired.

jingham added inline comments.Apr 28 2023, 11:19 AM
lldb/source/Host/macosx/objcxx/Host.mm
419–420

If both are set and not the same, maybe we should flag that. Maybe we can check when the setting is set, and if the environment variable is also set and different, we can warn at that point.

But the intention of the setting is to change what the current behavior is, no matter how we got to the current behavior, so the setting should take precedence.

JDevlieghere marked 10 inline comments as done.
  • Return an llvm::Erorr and percolate errors up
  • Don't fall back to the default editor if the one specified can't be found
  • Limit roles to editors only
bulbazord accepted this revision.Apr 28 2023, 12:26 PM

LGTM! Thanks for cleaning this up.

lldb/source/Target/Thread.cpp
1762–1763

Not related to this change but I don't think I like LLDB_LOG_ERROR... I read this and I think "Oh, if logging is disabled, will this actually consume the error?". After all, the other logging macros do not have a side effect. It'd be nice if we could create a function and name it "ConsumeErrorAndLog" or something to be clearer that it actually consumes it.