How to handle custom IntelliPrompt with CSharp Add-on?

SyntaxEditor .NET Languages Add-on for Windows Forms Forum

Posted 13 years ago by Erik Pepping - RADVenture B.V
Version: 4.0.0239
Avatar
I would like to be able to put selected index of the IntelliPrompt list on the "declaring type" after typing "myString = new<spacebar>", so the IntelliPrompts automatically highlights by default the "declaring type".

I 'm trying to do this by using SyntaxEditorIntelliPromptMemberListPreFilter. Here I can perfectly detect the New declaration and the "declaring type". But I don't have any clue how to handle this further. Could you please give some hints? Perhaps I should handle this completely different?
void csharpLanguage_SyntaxEditorIntelliPromptMemberListPreFilter(object sender, ActiproSoftware.SyntaxEditor.Addons.DotNet.Dom.IntelliPromptMemberListPreFilterEventArgs e)
{
    try
    {
        if (e.Context.Type == ActiproSoftware.SyntaxEditor.Addons.DotNet.Context.DotNetContextType.NewObjectDeclaration)
        {
            for (int i = editor.Document.Tokens.IndexOf(e.Context.TargetOffset)-1; i > 0; i--)
            {
                if (editor.Document.Tokens[i].Key == "Identifier")
                {
                    //The declaring type
                }
            }
        }
    }
    catch (Exception)
    {

    }
}
Erik Pepping

Comments (8)

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Erik,

I don't think these currently is a way to do it. How would you like to see this done, via another new SyntaxEditor event or somehow via this pre-filter? Please include your implementation ideas.


Actipro Software Support

Posted 13 years ago by Erik Pepping - RADVenture B.V
Avatar
Adding a new parameter to the pre-filter method sounds like the easiest way, but offering a new event after initialization of the IntelliPrompt window would probably be more flexible for other purposes too.

How would you suggest to handle the scenario below with the C# add-on langauge?
The developer types for example "this.Update(", through the SyntaxEditor reflection it is determined that the Update method is not overloaded and does not use any parameters, so the closing hook and semicolon are added.
With the XML CSharp language it was easy to use the triggers, how should we handle these kind of features?

Thanks again for the willingness to help.

Erik
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
I'm thinking a new event would be best for doing a pre-selection. That way the same feature can be done in any language as opposed to the .NET Languages add-on only. Unless we moved the pre-filtering stuff from the add-on to the main control so that could be done with any language as well. And then stick in a selection thing there.

For your other question, triggers can be added to any language, even the add-on. The keypress triggers simply check the state of the current token and look for a character match. You can implement that type of code yourself in OnSyntaxEditorKeyTyped. Or just add a trigger programmatically to the language.


Actipro Software Support

Posted 13 years ago by Erik Pepping - RADVenture B.V
Avatar
Thanks for the feedback. I'm looking forward to the new release.

I should have been clearer with my second question.

The developer has typed "this.Update(". Is it possible to get from the Caret.Offset to the reflection info (AstNode) for the Control method Update?

I tried several things like:
ICompilationUnit compilationUnit = (ICompilationUnit)editor.Document.SemanticParseData;
compilationUnit.FindNodeRecursive(editor.Caret.Offset - 2)
but that does give me specific reflection info about the current token, also the token itself does not seem to contain that info. Perhaps I'm missing the point/concept?

The Update example is a very simple example. The real purpose is to detect the usage of BO layer objects and offer a context sensitive menu for the detected type.
private void editor_KeyTyped(object sender, ActiproSoftware.SyntaxEditor.KeyTypedEventArgs e)
{
    if (e.KeyChar == '(')
    {
        if (editor.Document.Tokens.GetTokenAtOffset(editor.Caret.Offset).Language is ActiproSoftware.SyntaxEditor.Addons.CSharp.CSharpSyntaxLanguage)
        {
            if (editor.Caret.Offset - 2 >= 0
                && editor.Document.Tokens.GetTokenAtOffset(editor.Caret.Offset - 2).Key == "Identifier")
            {
                //the developer has typed "this.Update(" 
                //Is it possible to get from the Caret.Offset to the reflection info (AstNode) for the Control method Update?
                //I tried several things like
                //ICompilationUnit compilationUnit = (ICompilationUnit)editor.Document.SemanticParseData;
                //compilationUnit.FindNodeRecursive(editor.Caret.Offset - 2)
                //also the token itself does not give any reflection info.
            }
        }
    }
}
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Check out the CSharpContext class. It has some static methods on it that let you
determine the context of a specific offset in various scenarios. For parameter
info context, we call CSharpContext.GetContextBeforeOffset, so try that out.


Actipro Software Support

Posted 13 years ago by Erik Pepping - RADVenture B.V
Avatar
Thanks, step by step I'm getting closer, but I'm still having a hard time to get the simple case working. This is what I have so far:
private void editor_KeyTyped(object sender, KeyTypedEventArgs e)
{
    if (e.KeyChar == '(')
    {
        if (editor.Document.Tokens.GetTokenAtOffset(editor.Caret.Offset).Language is CSharpSyntaxLanguage)
        {
            if (editor.Caret.Offset - 2 >= 0
                && editor.Document.Tokens.GetTokenAtOffset(editor.Caret.Offset - 2).Key == "Identifier")
            {
                DotNetContext context = CSharpContext.GetContextBeforeOffset(editor.Document, editor.Caret.Offset, (CompilationUnit)editor.Document.SemanticParseData, dotNetProjectResolver, true);
                if (context.TargetItem.ResolvedInfo is MethodDeclaration && ((MethodDeclaration)context.TargetItem.ResolvedInfo).Parameters.Count == 0)
                {
                    editor.Document.InsertText(DocumentModificationType.Typing, editor.Caret.Offset, ");");
                }
            }
        }
    }
}
If I use this code in in the TestApplication-CSharp.Net20 and put a breakpoint after "DotNetContext context" and I type "this.Add(" in the test application I get Parameters.Count==2, which is what I expected. But if I type for example "this.Update(" the ResolvedInfo doesn't return a MethodDeclaration but an internal type.

I'm sorry to bother you again with more questions about this, but I'm unable to figure it out by myself.

Kind regards,

Erik Pepping.
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
If I stick this code directly in the 'if' check for the '(' character, it works:
CompilationUnit compilationUnit = syntaxEditor.Document.SemanticParseData as CompilationUnit;
DotNetProjectResolver projectResolver = syntaxEditor.Document.LanguageData as DotNetProjectResolver;
CSharpContext c = CSharpContext.GetContextBeforeOffset(syntaxEditor.Document, syntaxEditor.Caret.Offset, compilationUnit, projectResolver, true);
Also, I would highly recommend never casting to MethodDeclaration or TypeDeclaration, etc. Always cast to IDomType and IDomMember instead.


Actipro Software Support

Posted 13 years ago by Erik Pepping - RADVenture B.V
Avatar
Got it. Thanks for your patience.

Erik
The latest build of this product (v2018.1 build 0341) was released 8 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.