private IEnumerable <CompletionItem> GetModulePathCompletions(SemanticModel model, BicepCompletionContext context) { if (!context.Kind.HasFlag(BicepCompletionContextKind.ModulePath)) { return(Enumerable.Empty <CompletionItem>()); } // To provide intellisense before the quotes are typed if (context.EnclosingDeclaration is not ModuleDeclarationSyntax declarationSyntax || declarationSyntax.Path is not StringSyntax stringSyntax || stringSyntax.TryGetLiteralValue() is not string entered) { entered = ""; } // These should only fail if we're not able to resolve cwd path or the entered string if (FileResolver.TryResolveModulePath(model.SyntaxTree.FileUri, ".") is not { } cwdUri || FileResolver.TryResolveModulePath(cwdUri, entered) is not { } query) { return(Enumerable.Empty <CompletionItem>()); } var files = Enumerable.Empty <Uri>(); var dirs = Enumerable.Empty <Uri>(); // technically bicep files do not have to follow the bicep extension, so // we are not enforcing *.bicep get files command if (FileResolver.TryDirExists(query)) { files = FileResolver.GetFiles(query, string.Empty); dirs = FileResolver.GetDirectories(query, string.Empty); } else if (FileResolver.TryResolveModulePath(query, ".") is {} queryParent) { files = FileResolver.GetFiles(queryParent, ""); dirs = FileResolver.GetDirectories(queryParent, ""); } // "./" will not be preserved when making relative Uris. We have to go and manually add it. // Prioritize .bicep files higher than other files. var fileItems = files .Where(file => file != model.SyntaxTree.FileUri) .Where(file => file.Segments.Last().EndsWith(LanguageServerConstants.LanguageFileExtension)) .Select(file => CreateModulePathCompletion( file.Segments.Last(), (entered.StartsWith("./") ? "./" : "") + cwdUri.MakeRelativeUri(file).ToString(), context.ReplacementRange, CompletionItemKind.File, file.Segments.Last().EndsWith(LanguageServerConstants.LanguageId) ? CompletionPriority.High : CompletionPriority.Medium)) .ToList(); var dirItems = dirs .Select(dir => CreateModulePathCompletion( dir.Segments.Last(), (entered.StartsWith("./") ? "./" : "") + cwdUri.MakeRelativeUri(dir).ToString(), context.ReplacementRange, CompletionItemKind.Folder, CompletionPriority.Medium) .WithCommand(new Command { Name = EditorCommands.RequestCompletions })) .ToList(); return(fileItems.Concat(dirItems)); }