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

Add module path completions for ARM template files #3616

Merged
merged 6 commits into from
Jul 15, 2021

Conversation

shenglol
Copy link
Contributor

Closes #3595.

@shenglol shenglol changed the title Add completions for ARM template files Add module path completions for ARM template files Jul 15, 2021
@anthony-c-martin
Copy link
Member

Do you know what's going on here?
image

As a test, I copy+pasted a lot of the json files in a particular directory (docs/examples/101/api-management-modular/main.bicep), but only some of the copied files are showing up for completions. There are no scroll bars in the completion list, and I've tried reloading the extension and retrying. I'm testing this on OSX.

Note there's also the fact that space characters are being URL-encoded as %20 - but I suspect that's probably an existing issue.

Comment on lines 350 to 352
if ((PathHelper.HasExtension(fileUri, LanguageConstants.JsonFileExtension) ||
PathHelper.HasExtension(fileUri, LanguageConstants.JsoncFileExtension)) &&
this.FileResolver.TryRead(fileUri, out var fileContents, out var _, Encoding.UTF8, 2000, out var _))
Copy link
Member

Choose a reason for hiding this comment

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

Any perf concerns with this approach? It seems fast enough to me with ~500 files on a new-ish MacBook with an SSD, but could slow down with larger quantities of files or HDDs / other unusual disk configurations.

I get the need for it (as you don't want param files showing up), so not sure if we really have another option!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah this can definitely be slow with HDDs if there are a hundreds of files in the directory. Although I cannot think of a way to avoid reading the files (as you mentioned we don't want random JSON files showing up in the completion list), we are only checking the first 2000 characters of each JSON file, so the delay of loading completions is linear to the number of files and is not affected by file sizes.

Copy link
Member

Choose a reason for hiding this comment

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

I suspect we can go lower than 2000. The schema property is usually at the beginning and isn't that long. If the user decides to put it at the end of the long template, I think it's ok if the file doesn't show up in completions. For those cases, the user shouldn't be blocked because they can still write in a valid path.

I think there are a couple of options to preserve the experience if perf ends up being slow for some users:

  1. We can put in a hard time limiter in the logic. It could be as simple as starting a stopwatch. If elapsed time exceeds some threshold, we stop reading more file and don't return any of the JSON completions.
  2. We are already receiving notifications about all file events in a workspace (and discarding most of them). We could actually keep track of JSON files specifically and load them only when they are modified to determine if they are a template file. Then the completion logic would just have to query the cache.

Comment on lines 331 to 333
return model.Compilation.SourceFileGrouping.SourceFiles.Any(sourceFile =>
sourceFile is BicepFile &&
sourceFile.FileUri.LocalPath.Equals(fileUri.LocalPath, PathHelper.PathComparison));
Copy link
Member

Choose a reason for hiding this comment

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

Are you trying to account for non-.bicep files which are already part of the compilation? Personally, I think I'd prefer to just keep it purely extension-based, or the completion experience could be confusing. Some examples:

  1. I've got 2 non-.bicep files, only one referenced in my code. It may be unclear why only one shows up in completions.
  2. File completions may be influenced by whether or not there's a syntax error in the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good pt. We'd better make the user experience more consistent. I changed it to check .bicep extension only.

Comment on lines +343 to +345
if (model.Compilation.SourceFileGrouping.SourceFiles.Any(sourceFile =>
sourceFile is ArmTemplateFile &&
sourceFile.FileUri.LocalPath.Equals(fileUri.LocalPath, PathHelper.PathComparison)))
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to have ArmTemplateFiles in the source tree without the standard set of extensions? Or are you just trying to avoid having to run the read-from-disk block when possible?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it's not possible. If a referenced file's extension is not within the standard set of extensions (.arm, .json, .jsonc, .bicep), we assume the file to be a bicep file. And yes, this check is done before reading the file to avoid unnecessary I/O.

@shenglol
Copy link
Contributor Author

shenglol commented Jul 15, 2021

As a test, I copy+pasted a lot of the json files in a particular directory (docs/examples/101/api-management-modular/main.bicep), but only some of the copied files are showing up for completions. There are no scroll bars in the completion list, and I've tried reloading the extension and retrying. I'm testing this on OSX.

Note there's also the fact that space characters are being URL-encoded as %20 - but I suspect that's probably an existing issue.

Good catch 😅. This is indeed a bug. I misunderstood the purpose of the maxCharaters parameter of the FileResolver.TryRead method and didn't realize it will not return file contents when maxCharacters is hit. I've implemented a new method TryReadAtMostNCharaters to satisfy my need and added tests cases to cover this.

@@ -152,6 +150,39 @@ public bool TryReadAsBase64(Uri fileUri, [NotNullWhen(true)] out string? fileBas
}
}

public bool TryReadAtMostNCharaters(Uri fileUri, Encoding fileEncoding, int n, [NotNullWhen(true)] out string? fileContents)
Copy link
Member

Choose a reason for hiding this comment

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

n

Could also rename n to maxCharactersToRead

Copy link
Member

@majastrz majastrz left a comment

Choose a reason for hiding this comment

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

:shipit:

@anthony-c-martin anthony-c-martin enabled auto-merge (squash) July 15, 2021 19:55
@anthony-c-martin anthony-c-martin merged commit f1169d0 into main Jul 15, 2021
@anthony-c-martin anthony-c-martin deleted the shenglol/completions-for-arm-templates branch July 15, 2021 20:31
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.

Provide module path completions for ARM template files
3 participants