// Step 3: Implement the CreateTagger method to return an instance of HighlightWordTagger.
        public ITagger <T> CreateTagger <T>(ITextView textView, ITextBuffer buffer) where T : ITag
        {
            //provide highlighting only on the top buffer 
            if (textView.TextBuffer != buffer)
            {
                return(null);
            }

            string thisFile = VerilogLanguage.VerilogGlobals.GetDocumentPath(textView.TextSnapshot);

            // TODO - do we really want to reparse here??
            // this appears to be the only place called when first opening a file. (?)
            //
            // keywords: onload initialize startup
            //
            VerilogGlobals.ParseStatusController.Init(thisFile);

            //lock (VerilogGlobals.ParseStatus[thisFile])
            //{
            //    // VerilogGlobals.NeedReparse = true;
            //    VerilogGlobals.ParseStatus[thisFile].NeedReparse = true;
            //}
            // VerilogGlobals.ParseStatus_NeedReparse_SetValue(thisFile, true);
            VerilogGlobals.ParseStatusController.NeedReparse_SetValue(thisFile, true);

            VerilogGlobals.Reparse(buffer, thisFile); // parse the buffer at file load time

            ITextStructureNavigator textStructureNavigator =
                TextStructureNavigatorSelector.GetTextStructureNavigator(buffer);

            return(new HighlightWordTagger(textView, buffer, TextSearchService, textStructureNavigator) as ITagger <T>);
        }
Пример #2
0
        //private void Start()
        //{
        //    System.Diagnostics.Debug.WriteLine("1. Call thread task");

        //    StartMyLongRunningTask();

        //    System.Diagnostics.Debug.WriteLine("2. Do something else");
        //}

        //private void StartMyLongRunningTask()
        //{

        //    ThreadStart starter = myLongRunningTask;

        //    starter += () =>
        //    {
        //        myLongRunningTaskDone();
        //    };

        //    Thread _thread = new Thread(starter) { IsBackground = true };
        //    _thread.Start();
        //}

        //private void myLongRunningTaskDone()
        //{
        //    System.Diagnostics.Debug.WriteLine("3. Task callback result");
        //}

        //private void myLongRunningTask()
        //{
        //    string thisFile = VerilogLanguage.VerilogGlobals.GetDocumentPath(_buffer.CurrentSnapshot);
        //    VerilogGlobals.Reparse(_buffer, thisFile); // note that above, we are checking that the e.After is the same as the _buffer
        //}

        /// <summary>
        ///   BufferChanged - handle Buffer Changed event. If buffer has a character with possible far-reaching consequences
        ///                   then force a rescan of the enture buffer. See also HighlightWordTaggerProvider
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BufferChanged(object sender, TextContentChangedEventArgs e)
        {
            // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll eventually get another change event).
            if (e.After != _buffer.CurrentSnapshot)
            {
                return;
            }

            if (e.Changes.Count < 1)
            {
                // TODO - how did we get here if there are no changes? (found this after exception during debug. no apparent invoke. )
                return;
            }

            string theNewText = e.Changes[0].NewText;
            string theOldText = e.Changes[0].OldText;

            if (e.Changes.Count > 1)
            {
                // TODO - why exit if there is more than one change (perhaps exit if LESS than 1? no!)
                return;
            }


            // we are only interested when the old and new text are different.
            // yes, the event seems to be triggered even with no apparent changes
            //
            if (theNewText != theOldText)
            {
                // even if the buffer is different, only certain characters require a full reparse
                // typically brackets (since we keep track of depth) and comment chars:
                if (VerilogGlobals.IsRefreshChar(theNewText) || VerilogGlobals.IsRefreshChar(theOldText))
                {
                    string thisFile = VerilogLanguage.VerilogGlobals.GetDocumentPath(_buffer.CurrentSnapshot);

                    // VerilogGlobals.ParseStatus_NeedReparse_SetValue(thisFile, true);
                    VerilogGlobals.ParseStatusController.NeedReparse_SetValue(thisFile, true);
                    //VerilogGlobals.ParseStatus_EnsureExists(thisFile);
                    //VerilogGlobals.ParseStatus[thisFile].NeedReparse = true;
                    // VerilogGlobals.NeedReparse = true;

                    //myLongRunningTask();
                    VerilogGlobals.Reparse(_buffer, thisFile); // note that above, we are checking that the e.After is the same as the _buffer
                }
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("BufferChanged called but new and old text not different!");
            }
        }
 // Step 4: The event handlers both call the UpdateAtCaretPosition method.
 void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
 {
     // If a new snapshot wasn't generated, then skip this layout 
     if (e.NewSnapshot != e.OldSnapshot)
     {
         UpdateAtCaretPosition(View.Caret.Position);
         string thisFile = VerilogLanguage.VerilogGlobals.GetDocumentPath(View.TextSnapshot);
         //VerilogGlobals.ParseStatus_EnsureExists(thisFile);
         //VerilogGlobals.ParseStatus[thisFile].NeedReparse = true;
         // VerilogGlobals.ParseStatus_NeedReparse_SetValue(thisFile, true);
         ParseStatusController.NeedReparse_SetValue(thisFile, true);
         //VerilogGlobals.NeedReparse = true;
         VerilogGlobals.Reparse(SourceBuffer, thisFile);
     }
 }
        /// <summary>
        ///   BufferChanged - handle Buffer Changed event. If buffer has a character with possible far-reaching consequences
        ///                   then force a rescan of the enture buffer. See also HighlightWordTaggerProvider
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BufferChanged(object sender, TextContentChangedEventArgs e)
        {
            // If this isn't the most up-to-date version of the buffer, then ignore it for now (we'll eventually get another change event).
            if (e.After != _buffer.CurrentSnapshot)
            {
                return;
            }

            string theNewText = e.Changes[0].NewText;
            string theOldText = e.Changes[0].OldText;

            if (e.Changes.Count > 1)
            {
                return;
            }


            // we are only interested when the old and new text are different.
            // yes, the event seems to be triggered even with no apparent changes
            //
            if (theNewText != theOldText)
            {
                // even if the buffer is different, only certain characters require a full reparse
                // typically brackets (since we keep track of depth) and comment chars:
                if (VerilogGlobals.IsRefreshChar(theNewText) || VerilogGlobals.IsRefreshChar(theOldText))
                {
                    string thisFile = VerilogLanguage.VerilogGlobals.GetDocumentPath(_buffer.CurrentSnapshot);

                    // VerilogGlobals.ParseStatus_NeedReparse_SetValue(thisFile, true);
                    VerilogGlobals.ParseStatusController.NeedReparse_SetValue(thisFile, true);
                    //VerilogGlobals.ParseStatus_EnsureExists(thisFile);
                    //VerilogGlobals.ParseStatus[thisFile].NeedReparse = true;
                    // VerilogGlobals.NeedReparse = true;
                    VerilogGlobals.Reparse(_buffer, thisFile); // note that above, we are checking that the e.After is the same as the _buffer
                }
            }
        }
Пример #5
0
        /// <summary>
        ///   IEnumerable VerilogTokenTag GetTags
        /// </summary>
        /// <param name="spans"></param>
        /// <returns></returns>
        public IEnumerable <ITagSpan <VerilogTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            //while (VerilogGlobals.IsReparsing)
            {
                // do we really want to do this? (probably not)
                // System.Threading.Thread.Sleep(10);
            }


            //System.Diagnostics.Debug.WriteLine("Starting IEnumerable<ITagSpan<VerilogTokenTag>>");
            // bool EditInProgress = spans.snapshot.TextBuffer.EditInProgress;
            // since we can start mid-text, we don't know if the current span is in the middle of a comment

            // init TODO - we don't really want to call this for every enumeration!
            // VerilogGlobals.InitHoverBuilder();
            VerilogGlobals.IsContinuedBlockComment = IsOpenBlockComment(spans); // TODO - does spans always contain the full document? (appears perhaps not)
            VerilogGlobals.VerilogToken[] tokens     = null;
            VerilogGlobals.VerilogToken   priorToken = new VerilogGlobals.VerilogToken();

            // look at each span for tokens, comments, etc
            foreach (SnapshotSpan curSpan in spans)
            {
                if (tokens != null && tokens.Length >= 1)
                {
                    priorToken = tokens[tokens.Length - 1]; // get the token from the prior line
                }
                ITextSnapshotLine containingLine = curSpan.Start.GetContainingLine();
                int    curLoc          = containingLine.Start.Position;
                int    LinePosition    = 0;
                string thisTokenString = "";

                tokens = VerilogGlobals.VerilogKeywordSplit(containingLine.GetText(), priorToken);

                Boolean IsContinuedLineComment = false;                      // comments with "//" are only effective for the current line, but /* can span multiple lines
                foreach (VerilogGlobals.VerilogToken VerilogToken in tokens) // this group of tokens in in a single line
                {
                    // by the time we get here, we might have a tag with adjacent comments:
                    //     assign//
                    //     //assign
                    //     assign//comment
                    //     /*assign*/
                    //     assign/*comment*/
                    thisTokenString = VerilogToken.Part;
                    CommentHelper commentHelper = new CommentHelper(thisTokenString,
                                                                    IsContinuedLineComment,
                                                                    VerilogGlobals.IsContinuedBlockComment);
                    VerilogGlobals.IsContinuedBlockComment = commentHelper.HasBlockStartComment;
                    IsContinuedLineComment = commentHelper.HasOpenLineComment; // we'll use this when processing the VerilogToken item in the commentHelper, above

                    foreach (CommentHelper.CommentItem Item in commentHelper.CommentItems)
                    {
                        bool TestComment = VerilogGlobals.TextIsComment(containingLine.LineNumber, LinePosition);
                        LinePosition += Item.ItemText.Length;

                        var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLoc, Item.ItemText.Length));
                        if (tokenSpan.IntersectsWith(curSpan))
                        {
                            // is this item a comment? If so, color as appropriate. comments take highest priority: no other condition will change color of a comment
                            if (Item.IsComment)
                            {
                                // System.Diagnostics.Debug.WriteLine("IEnumerable VerilogTokenTag yield comment for item " + Item.ItemText??"");
                                yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                           new VerilogTokenTag(VerilogTokenTypes.Verilog_Comment)));
                            }

                            // otherwise when not a comment, check to see if it is a keyword
                            else
                            {
                                // first check to see if any new variables are being defined;

                                // VerilogGlobals.BuildHoverItems(Item.ItemText);


                                // check for standard keyword syntax higlighting
                                if (VerilogGlobals.VerilogTypes.ContainsKey(Item.ItemText))
                                {
                                    System.Diagnostics.Debug.WriteLine("IEnumerable VerilogTokenTag yield " + Item.ItemText);
                                    yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                               new VerilogTokenTag(VerilogGlobals.VerilogTypes[Item.ItemText])));
                                }
                                else if (VerilogGlobals.VerilogVariables.ContainsKey(Item.ItemText))
                                {
                                    // we are instantiation a module; recall VerilogVariables is first a dictionary of scope (aka module), then a dictionary of variables in each module scope
                                    // TODO do we need: if (tokenSpan.IntersectsWith(curSpan))
                                    System.Diagnostics.Debug.WriteLine("IEnumerable VerilogTokenTag yield variable module " + Item.ItemText);
                                    yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                               new VerilogTokenTag(VerilogGlobals.VerilogTypes["variable_module"])));
                                }
                                else
                                {
                                    // check to see if this is a variable
                                    string thisScope = VerilogGlobals.TextModuleName(containingLine.LineNumber, curLoc - containingLine.Start.Position); // TODO
                                    if (VerilogGlobals.VerilogVariables.ContainsKey(thisScope))
                                    {
                                        // the current scope (typically a module name) is defined. So do we have a known variable?
                                        if (VerilogGlobals.VerilogVariables[thisScope].ContainsKey(Item.ItemText))
                                        {
                                            // TODO do we need: if (tokenSpan.IntersectsWith(curSpan))
                                            System.Diagnostics.Debug.WriteLine("IEnumerable VerilogTokenTag yield variable " + Item.ItemText);
                                            yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                       new VerilogTokenTag(VerilogGlobals.VerilogVariables[thisScope][Item.ItemText])));
                                        }

                                        else if (VerilogGlobals.VerilogVariables.ContainsKey(VerilogGlobals.SCOPE_CONST) && VerilogGlobals.VerilogVariables[VerilogGlobals.SCOPE_CONST].ContainsKey(Item.ItemText))
                                        {
                                            yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                       new VerilogTokenTag(VerilogGlobals.VerilogVariables[VerilogGlobals.SCOPE_CONST][Item.ItemText])));
                                        }

                                        else
                                        {
                                            // no tag colorization for the explicit token, but perhaps based on context:
                                            int thisDelimiterIndex = 0;
                                            int thisDelimiterTotalDepth;
                                            //int thisDelimiterTotalDepth = VerilogToken.SquareBracketDepth +
                                            //                              VerilogToken.RoundBracketDepth +
                                            //                              VerilogToken.SquigglyBracketDepth;
                                            // int testValue = VerilogGlobals.BracketDepth(containingLine.LineNumber, curLoc - containingLine.Start.Position);
                                            switch (VerilogToken.Context)
                                            {
                                            case VerilogGlobals.VerilogTokenContextType.SquareBracketOpen:
                                            case VerilogGlobals.VerilogTokenContextType.SquareBracketClose:
                                                thisDelimiterTotalDepth = VerilogGlobals.BracketDepth(containingLine.LineNumber, curLoc - containingLine.Start.Position);
                                                thisDelimiterIndex      = (thisDelimiterTotalDepth % 5);
                                                yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                           // see _VerilogTypes["bracket_type1"] .. _VerilogTypes["bracket_type5"]
                                                                                           new VerilogTokenTag(VerilogGlobals.VerilogTypes["bracket_type" + (thisDelimiterIndex).ToString()])));

                                                break;

                                            case VerilogGlobals.VerilogTokenContextType.RoundBracketClose:
                                            case VerilogGlobals.VerilogTokenContextType.RoundBracketOpen:
                                                thisDelimiterTotalDepth = VerilogGlobals.BracketDepth(containingLine.LineNumber, curLoc - containingLine.Start.Position);
                                                thisDelimiterIndex      = (thisDelimiterTotalDepth % 5);
                                                yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                           // see _VerilogTypes["bracket_type1"] .. _VerilogTypes["bracket_type5"]
                                                                                           new VerilogTokenTag(VerilogGlobals.VerilogTypes["bracket_type" + (thisDelimiterIndex).ToString()])));

                                                break;

                                            case VerilogGlobals.VerilogTokenContextType.SquigglyBracketOpen:
                                            case VerilogGlobals.VerilogTokenContextType.SquigglyBracketClose:
                                                thisDelimiterTotalDepth = VerilogGlobals.BracketDepth(containingLine.LineNumber, curLoc - containingLine.Start.Position);
                                                thisDelimiterIndex      = (thisDelimiterTotalDepth % 5);
                                                // see _VerilogTypes["bracket_type1"] .. _VerilogTypes["bracket_type5"]
                                                yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                           new VerilogTokenTag(VerilogGlobals.VerilogTypes["bracket_type" + (thisDelimiterIndex).ToString()])));

                                                break;

                                            case VerilogGlobals.VerilogTokenContextType.SquareBracketContents:
                                                yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                           new VerilogTokenTag(VerilogTokenTypes.Verilog_BracketContent)));

                                                break;

                                            case VerilogGlobals.VerilogTokenContextType.AlwaysAt:
                                                yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                           new VerilogTokenTag(VerilogTokenTypes.Verilog_always)));

                                                break;

                                            default:
                                                // no highlighting
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (VerilogGlobals.VerilogVariables.ContainsKey(VerilogGlobals.SCOPE_CONST) && VerilogGlobals.VerilogVariables[VerilogGlobals.SCOPE_CONST].ContainsKey(Item.ItemText))
                                        {
                                            //yield return new TagSpan<VerilogTokenTag>(tokenSpan,
                                            //      new VerilogTokenTag(VerilogGlobals.VerilogTypes["Verilog_Value"]));
                                            yield return(new TagSpan <VerilogTokenTag>(tokenSpan,
                                                                                       new VerilogTokenTag(VerilogGlobals.VerilogVariables[VerilogGlobals.SCOPE_CONST][Item.ItemText])));
                                        }
                                        else
                                        {
                                            // TODO - how do we get here when thisScope *is* defined? timing?
                                            // A: we destroy the VerilogVariables when rescanning (otherwise everyuthing is a duplicate) TODO: keep track of where variables are defined. don't rebui;d
                                            System.Diagnostics.Debug.WriteLine("Warning! VerilogGlobals.VerilogVariables.ContainsKey({0}) not defined!", thisScope);
                                        }
                                    }
                                }
                            }
                        }

                        // note that no chars are lost when splitting string with VerilogKeywordSplit, so no adjustment needed in location
                        curLoc += Item.ItemText.Length;
                    }
                }
            }
        }