Completion List Behavior in SyntaxEditor for C# Language

SyntaxEditor .NET Languages Add-on for WPF Forum

The latest build of this product (v25.1.4) was released 3 months ago, which was before this thread was created.
Posted 2 months ago by miles
Version: 24.1.2
Platform: .NET 6
Environment: Windows 11 (64-bit)
Avatar
Hi, we are developing a C# script editor with IntelliSense capabilities in a WPF application.

## Background
* Environment: TargetFramework=net6.0-windows, Actipro=v24.1.2
* We would like the editor to support code completion equivalent to `RoslynPad` as much as possible.
* Additionally, our application has the following requirements:
  * Register assemblies containing our custom API and enable code completion without requiring users to write `using` directives.
  * Support host variables defined by the application, allowing users to use them in the editor without any special declarations.
  * Support top-level statement syntax in C# scripts.
  * Allow users to write custom `using` directives within the text.
    * However, code completion for classes in user-added namespaces is not required.

## Questions

**Question 1**

* In RoslynPad, by specifying a host object type when creating a project during control initialization, the properties defined on that type are recognized as host variables and appear in the code completion list.
  * https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.projectinfo.hostobjecttype?view=roslyn-dotnet-4.13.0#microsoft-codeanalysis-projectinfo-hostobjecttype
* Is it possible to specify a host object type in a similar way with SyntaxEditor to expose its members to the script?
* If so, could you provide a concrete implementation example?

* Additional notes:
  * We are currently achieving this through the following workaround.
  * However, with this approach, the host variables do not consistently appear as completion candidates, and we are unable to achieve stable code completion.
    * Immediately after opening the editor, typing the first character of a host variable as a top-level statement does not show it as a completion candidate.
    * After typing some other code, the host variable may eventually appear as a candidate in top-level statements.
    * In statements on the second line or later, the host variables appear as expected (as far as we have observed).

1. Define a container class for the host variables.
   For example, to make the host variable `App` available, define a static class like the following:
   ```cs
   public static class __ScriptHostVariableContainer
   {
      public static IApp App;       // Define a static field.
   }

   ```
2. Statically import the container class via the SyntaxEditor's header text.
   ```cs
   public void initializeEditor(SyntaxEditor editor, Type hostObjectType)
   {
      var header = new StringBuilder();
      // Use static imports to access static members of the container class.
      header.AppendLine($"using static {hostObjectType.FullName};");
      header.AppendLine();

      // It is hidden in the header text so that it is not displayed on the UI.
      editor.Document.SetHeaderAndFooterText(header.ToString(), string.Empty);
   }
   ```

**Question 2**

* In RoslynPad, code completion (including member completion) works inside `{}` expressions in interpolated strings.
* Is it possible to display the completion list for expressions inside `{}` in interpolated strings with SyntaxEditor as well?
* If so, could you provide a concrete implementation example?

```cs
var hoge = new Hoge("Alice");

// When I type "hoge." below, I want the members of the Hoge class to be displayed as suggestions, but they are not being displayed.
var message = $"Hello {hoge.Name}!";

return message;

class Hoge
{
    public string Name {get;}
    public string Prop1 {get;set;}
    public Hoge(string name){ Name = name;}
}

```
Thanks in advance!

Comments (4)

Posted 2 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Miles,

Thanks for the details. It looks like you’re working from an older version. I recommend testing your scenarios in the latest build, since you’ll be happy to see that for question #2, interpolated string expression syntax highlighting and IntelliPrompt features were added in v25.1. This blog post includes a screenshot of the new functionality.

Regarding question #1, I simplified the scenario into a small document you can paste directly into the main SDI Editor demo in the latest version. The sample includes a comment indicating where the "header" break would conceptually occur once this scenario is fully supported.

using static __ScriptHostVariableContainer;

public static class __ScriptHostVariableContainer
{
   public static string App;       // Define a static field.
}

// Header ends here

// "App" doesn't seem to be resolved here (top-level)

class Foo {
	void Bar() {
		// "App" completion works here:
		App.
	}
}

After pasting the code, I’m seeing that IntelliPrompt resolution for “App” does not work at the top level (near the comment), but it does resolve correctly inside a method. Are you seeing the same behavior on your side? If so, it seems that enabling top‑level resolution to behave like method‑level resolution would give you the result you’re looking for. Can you confirm that sort of update would meet your needs?

Best regards,

[Modified 2 months ago]


Actipro Software Support

Posted 2 months ago by miles
Avatar

Thank you for the prompt response.

After pasting the code, I'm seeing that IntelliPrompt resolution for "App" does not work at the top level (near the comment), but it does resolve correctly inside a method. Are you seeing the same behavior on your side?

Yes, we are seeing the same behavior on our side.

In addition, we have confirmed that "App" does appear as a completion candidate in the following cases:

  • Even in top-level statements, when a ";" or "{" exists later in the document (e.g., on a subsequent line), and the user begins typing at a position before that character.
  • Even in top-level statements, when a {} block scope is defined and the user begins typing inside that scope.

Based on the above observations, we also tried pre-setting {} in the footer text as a workaround, but this approach did not cause "App" to appear as a completion candidate.

If so, it seems that enabling top‑level resolution to behave like method‑level resolution would give you the result you're looking for. Can you confirm that sort of update would meet your needs?

Yes. Even without direct host variable support, that would meet our needs.

As a follow-up, could you confirm our understanding of the following?

  • There is currently no straightforward way to make top-level resolution behave like method-level resolution in either v24.1 (which we are currently using) or the released v25.1.
  • Support for making top-level resolution behave like method-level resolution would be included from the next release onward.

If there is a way to achieve this behavior in the current version, we would appreciate it if you could provide an implementation example.

Thanks,

Answer - Posted 2 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Miles,

This took a while to dig into since it actually was a very difficult problem to solve.  We only try to create a stub "Program" class for wrapping top-level statements when an actual statement is present.  I think that's why you partially saw it working if you had a statement underneath.  A stub class is required for resolution to function properly.

We've made a number of internal updates to our code for v26.1 (which is being prepped for release in the coming weeks) that gets everything working.  With that, I can do this:

using static System.Math;|

Where the caret at the | and I press Ctrl+Space.  Then I see the Math methods like Ceiling properly showing up.

This also works great in our v26.1 Code Fragments QuickStart where I put the using line in the header text and have an empty main document and press Ctrl+Space.  There I also see the Math methods popping up in IntelliPrompt completion.

We attempted find workarounds for the current versions (< 26.1) without internal code changes, but unfortunately nothing purely using header/footer text seemed to get it working reliably.

[Modified 2 months ago]


Actipro Software Support

Posted 2 months ago by miles
Avatar
Thank you for the thorough investigation and fix.
We look forward to the v26.1 release and will verify both scenarios (top-level resolution and interpolated string completion) once it becomes available.

Thanks again for the great support!

Add Comment

Please log in to a validated account to post comments.