Skip to content
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

Use dafny: Uris for standard library files #4832

Merged

Conversation

keyboardDrummer
Copy link
Member

@keyboardDrummer keyboardDrummer commented Dec 1, 2023

Description

  • For Dafny content that is embedded in the Dafny CLI, such as the standard library, expose their URIs using the dafny: scheme. This can be used by the LSP client to implement custom behavior for opening these files.

How has this been tested?

  • Added the test StandardLibraryTest.GotoDefinition

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

@@ -23,6 +24,13 @@ public class DafnyFile {

public static DafnyFile CreateAndValidate(ErrorReporter reporter, IFileSystem fileSystem,
DafnyOptions options, Uri uri, IToken origin) {

if (uri.Scheme == "doo") {
Copy link
Member Author

Choose a reason for hiding this comment

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

VSCode only allows you to have custom handlers for custom schemes, which seems fair to me, but it means we have to introduce a doo: scheme, which is at odds with that we already handle the .doo extension as being special, even if no doo: scheme is used. That's why the code looks a bit funky now.

If we were more strict, only allowing doo files being used as libraries, and only allowing dfy files being used as sources, then we wouldn't need to rely on the extension checking, but that seems like something to consider for the future.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, this seems wrong enough to me to not do it at all - it really is abusing the URI scheme concept. It seems like letting VSCode understand the dllresource: scheme is part of the solution, but it also needs to understand that .doo is different content format independently.

Copy link
Member

Choose a reason for hiding this comment

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

Could we have a custom handler for dllresource: that says "if the URI ends with .doo ... else open like a normal Dafny file"? That would at least handle the standard libraries, even if we'll need to make more changes to handle doo files in general.

@@ -23,6 +24,13 @@ public class DafnyFile {

public static DafnyFile CreateAndValidate(ErrorReporter reporter, IFileSystem fileSystem,
DafnyOptions options, Uri uri, IToken origin) {

if (uri.Scheme == "doo") {
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, this seems wrong enough to me to not do it at all - it really is abusing the URI scheme concept. It seems like letting VSCode understand the dllresource: scheme is part of the solution, but it also needs to understand that .doo is different content format independently.

@keyboardDrummer keyboardDrummer changed the title Different uri for doo file Use dafny: Uris for standard library files Dec 4, 2023
@keyboardDrummer keyboardDrummer enabled auto-merge (squash) December 5, 2023 11:07
Copy link
Member

@robin-aws robin-aws left a comment

Choose a reason for hiding this comment

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

Thanks for the change, I definitely like the dafny: version better. Just some questions.

@@ -16,13 +18,30 @@ public class DafnyFile {
public string BaseName { get; private set; }
public bool IsPreverified { get; set; }
public bool IsPrecompiled { get; set; }
public bool IsPrerefined { get; private set; }
Copy link
Member

Choose a reason for hiding this comment

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

Off topic but when did this appear and what was it used for?

Copy link
Member Author

Choose a reason for hiding this comment

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

It was needed when .doo files still contained resolved code instead of just parsed code.

Copy link
Member

Choose a reason for hiding this comment

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

Okay good, I figured it was related but wasn't sure if was actually in sync before.

@@ -131,7 +130,7 @@ public class ManifestData {
}

var success = true;
var relevantOptions = currentCommand.Options.ToHashSet();
var relevantOptions = options.Options.OptionArguments.Keys.ToHashSet();
Copy link
Member

Choose a reason for hiding this comment

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

Is this still correct, given the comment immediately below? i.e. is OptionArguments.Keys the set of valid parameters for the current command, or just the options explicitly provided on the CLI or in project files?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is still correct, yes

private static readonly Dictionary<Uri, Uri> ExternallyVisibleEmbeddedFiles = new();

public static Uri ExposeInternalUri(string externalName, Uri internalUri) {
var externalUri = new Uri("dafny:" + externalName);
Copy link
Member

Choose a reason for hiding this comment

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

Why not just use $"dafny:{internalUri}"? That would be simpler and leaves the door open for other schemes. AFAICT attaching a fake Dafny file name doesn't help the IDE but perhaps I'm missing something.

Copy link
Member Author

@keyboardDrummer keyboardDrummer Dec 5, 2023

Choose a reason for hiding this comment

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

Because I didn't want to expose the implementation details of internalUri. Is there are a downside to having this mapping, except for it being slightly more work?

Copy link
Member

Choose a reason for hiding this comment

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

No real objection to the complexity/work, but a little worried about exposing "DafnyStandardLibraries.dfy" when that string/file name isn't actually meaningful. Eventually I expect the IDE will be able to actually open the doo file, and we shouldn't hide the fact that the source is coming from a doo file (especially to be clear it's read-only)

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually I added the dot dfy at the end so the IDE can recognize it's Dafny code and provide ide tooling on it.

I think from the user perspective, opening a dotdfy file to view the sources inside a dotdoo file, seems good

Copy link
Member

Choose a reason for hiding this comment

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

Okay, I can live with it :)

Copy link
Member Author

@keyboardDrummer keyboardDrummer Dec 6, 2023

Choose a reason for hiding this comment

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

We can still change the part after the dafny: in a follow-up PR, so let's not get hung up on this

I think, as part of adding .doo files, we should have added IDE navigation for .doo files as well, and then we would have already solved this. I think it would help with correctly designing .doo files as well. For example, we could have considered not making dotdoo a compressed file and instead having it be a single text file, so the IDE can open it directly, without the need for a dafny doo/library source command. Not saying we should have gone for that option, but at least we would have had a reason to consider it.

Thinking about dotdoo support in the IDE more, and given the way dotdoo files are currently structured, the dafny doo/library source command should support both on-disk files and files internal to the CLI, so it does need to take a URI, and then the dafny: uris exposed to the IDE should probably contain a URI after the dafny:. The IDE will chop off the dafny: part and pass the rest to dafny doo source

Copy link
Member

Choose a reason for hiding this comment

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

For example, we could have considered not making dotdoo a compressed file and instead having it be a single text file, so the IDE can open it directly, without the need for a dafny doo/library source command.

I definitely intended to iterate on the file format as we added features, and hence why the manifest has a doo_file_version property. :) But I don't think I'd want to make it a single text file, since then the manifest information would have to be embedded in comments or something like that, which would make it a bit tougher to read robustly and harder to hide that implementation detail from users.

Thinking about dotdoo support in the IDE more, and given the way dotdoo files are currently structured, the dafny doo/library source command should support both on-disk files and files internal to the CLI, so it does need to take a URI, and then the dafny: uris exposed to the IDE should probably contain a URI after the dafny:. The IDE will chop off the dafny: part and pass the rest to dafny doo source

Yup, this is one of the reasons I thought $"dafny:{internalUri}" would be smart, but you expressed it better than I managed at the time. :)

robin-aws
robin-aws previously approved these changes Dec 5, 2023
// Don't perform linting on doo files in general, since the source has already been processed.
internal override void PostResolve(ModuleDefinition moduleDefinition) {
if (moduleDefinition.tok.Uri != null && moduleDefinition.tok.Uri.LocalPath.EndsWith(".doo")) {
if (moduleDefinition.tok.Uri != null && !moduleDefinition.ShouldVerify(compilation)) {
Copy link
Member

Choose a reason for hiding this comment

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

For the record I think this is a step backwards in terms of accuracy: not linting doo files is more about the fact that the content is read-only to consumers and not their responsibility to lint, nothing to do with verification.

I don't want to block this change on it, but perhaps we could at least add a comment in the next related PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm wondering whether ShouldVerify should be renamed to ShouldCheck.

The reasoning behind not verifying a file seem to apply to other correctness checks as well.

@keyboardDrummer keyboardDrummer merged commit c90c6b4 into dafny-lang:master Dec 6, 2023
20 checks passed
@keyboardDrummer keyboardDrummer deleted the differentUriForDooFile branch December 6, 2023 17:12
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