Syntax editor: quick info prompt dose not show on hover of squiggle tag

SyntaxEditor for WPF Forum

Posted 1 month ago by Mattias Ström
Version: 24.1.5
Avatar

The tag squiggle line is present and the parser tags has quick info but my custome tagger shows the squiggle lines but without quick info prompt, how to fix this?

    public ExpressionsSyntaxLanguage() : 
            base("Expressions") {

        // Create a classification type provider and register its classification types
        ExpressionsClassificationTypeProvider classificationTypeProvider = new ExpressionsClassificationTypeProvider();
        classificationTypeProvider.RegisterAll();
      
        // Register an ILexer service that can tokenize text
        this.RegisterService<ILexer>(new ExpressionsLexer(classificationTypeProvider));                        
        
        // Register an ICodeDocumentTaggerProvider service that creates a token tagger for
        //   each document using the language
        this.RegisterService(new ExpressionsTokenTaggerProvider(classificationTypeProvider));

        // Register a squiggle tag quick info provider
        this.RegisterService(new SquiggleTagQuickInfoProvider());

        // Register a parser
        this.RegisterParser(new ExpressionsParser());

        // Register a tagger provider for showing parse errors
        this.RegisterService(new CodeDocumentTaggerProvider<ParseErrorTagger>(typeof(ParseErrorTagger)));            

        this.RegisterService<ICompletionProvider>(new ExpressionsCompletionProvider());

        this.RegisterService(new TextViewTaggerProvider<ViewModelAwareTagger>(typeof(ViewModelAwareTagger)));            
    }
}
public class ViewModelAwareTagger : TaggerBase<ISquiggleTag>
{
    private readonly IEditorView _view;

    public ViewModelAwareTagger(IEditorView view) : base("Custom",
        null, view.SyntaxEditor.Document, true)
    {
        _view = view;
    }

    public override IEnumerable<TagSnapshotRange<ISquiggleTag>> GetTags(NormalizedTextSnapshotRangeCollection snapshotRanges, object parameter)
    {
        if (snapshotRanges != null)
        {

            foreach (var snapshotRange in snapshotRanges)
            {
                var text = snapshotRange.Text;
                if (_view.SyntaxEditor.Tag is PropertyDescriptorPropertyModel descriptorPropertyModel && descriptorPropertyModel.Target is BaseFirmwareViewModel vm)
                {
                    foreach (var error in LogicalExpressionValidationHelper.Validate(text, vm))
                    {
                        var tag = new SquiggleTag(ClassificationTypes.SyntaxError, new PlainTextContentProvider(error.Message));

                        var targetSnapshotRange = snapshotRange;
                        if (targetSnapshotRange.IsZeroLength)
                        {
                            targetSnapshotRange = new TextSnapshotRange(targetSnapshotRange.Snapshot, targetSnapshotRange.StartOffset, targetSnapshotRange.StartOffset + 1);
                        }

                        yield return new TagSnapshotRange<ISquiggleTag>(TextSnapshotRange.FromSpan(targetSnapshotRange.Snapshot,
                                targetSnapshotRange.StartOffset + error.MatchIndex, error.MatchLength), tag);
                    }
                }
            }
        }
    }
}

[Modified 1 month ago]

Comments (6)

Posted 1 month ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

Nothing stands out as incorrect there since it appears you are creating the SquiggleTag with a quick info content provider, you said squiggles are appearing, and you've registered the SquiggleTagQuickInfoProvider language service. 

We can take a look at it if you make a new simple sample project that shows it happening and send that to our support address.  Reference this thread in your email and exclude the bin/obj folders from the .zip you send.  Then we can debug with that and see where things are going wrong.


Actipro Software Support

Posted 1 month ago by Mattias Ström
Avatar

The sample is sent

Posted 1 month ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Thank you for sending the sample.  I've run the sample locally and the QuickInfo is appearing as expected.  All I do is run the sample, type any text in the editor, and then hover over the text with the squiggle.  When I do, I see the QuickInfo message "Parsing completed before reaching document end."

I even tried installing a new instance of Visual Studio in Windows 11 Sandbox (which is a clean environment) and running your sample there.  I had the same result.

Are you able to reproduce the issue on more than one machine?

I do wonder if perhaps there's a z-order problem and the QuickInfo is appearing behind the window.  If you run using Visual Studio and have the Live Visual Tree tool window open when running, you should, by default, see an entry for "[MainWindow]" when the application launches.  When I hover over the squiggle tag, I see "[PopupRoot]" appear as well.  If you see "[PopupRoot]" but don't see the actual popup, it could be behind the window.


Actipro Software Support

Posted 1 month ago by Mattias Ström
Avatar

Hi

Can you please test writing prop[1]? You’ll see a squiggly line added by ViewModelAwareTagger, but the Quick Info tooltip ("Happy to see you") defined for the tag doesn’t appear on hover. 
Please note that I do see the quick info if write prop[] and this is generated by the pareser "Tocken tagger".

Posted 1 month ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Thank you for providing the steps to reproduce what you were seeing.  The issue appears to be that your ViewModelAwareTagger.GetTags method currently contains test logic to return a SquiggleTag for the TextSnapshotRange that was passed to it instead of using real data.

The GetTags method is first called for each view line to determine where squiggle tags should be rendered.  For this call, you are creating a valid squiggle tag that spans the length of the line, and that's why you see the squiggle being rendered.

Later, when you hover over the tag for QuickInfo, the GetTags method is called again with a zero-length TextSnapshotRange for the offset where the pointer was positioned.  At this point, you are creating a new tag for the zero-length range instead of returning a tag consistent with the previous call.  Since the new tag starts and ends at the same offset for the QuickInfo, it technically doesn't "contain" the offset and that's why QuickInfo ignores that tag.

Normally the GetTags method returns tags based on a collection of data that does not change.  Parse errors for the current snapshot are an example of this type of data.  When GetTags is called for parse errors, you iterate the existing collection of errors looking for those that are within the request snapshot range.  In the same scenario from above, the first time GetTags is called it would return all the parse errors for that line.  When it is later called for QuickInfo, it would only return the parse error from the offset where QuickInfo was requested.

As a quick test, I updated your logic for GetTags so that the TextSnapshotRange you create always uses a length of 1 instead of "snapshotRange.Length" (which would be zero for the QuickInfo call).  If I do that, I see a sqiggle tag that is 1 character wide and displays the expected text for QuickInfo.

Looking back at your original code (which is different than the sample you provided), I see that you are attempting to pull your error information from a view model, so that's good since the data shouldn't change.  I think the issue is that you are setting your "text" variable to "snapshotRange.Text".  When GetTags is called for the view line, that text is the entire line.  When it is called for QuickInfo, that text will be empty (due to zero-length snapshot range).  Perhaps all you need to do is change how you read text so that it always reads text for the entire line?

var text = snapshotRange.StartLine.Text;
var tag = new SquiggleTag(ClassificationTypes.SyntaxError, new PlainTextContentProvider("Happy to see you"));
yield return new TagSnapshotRange<ISquiggleTag>(TextSnapshotRange.FromSpan(snapshotRange.Snapshot,
    snapshotRange.StartLine.StartOffset, text.Length), tag);

Keep in mind that this approach means you are validating that text every time tags are queried for the line.  Depending on the complexity of your validation routine, that could lead to performance issues.  If it does, consider caching the tag information so that you only generate it once instead of each time tags are requested.


Actipro Software Support

Posted 1 month ago by Mattias Ström
Avatar

That worked, Thanks for the through analysis.

The latest build of this product (v25.1.0) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.