主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ
書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。
2016/05/29
本筋からはちょっとズレますが、あると嬉しい機能である、ツールチップ表示を実装します。
画像のように、テキスト上にカーソルを持って行くと表示されるあれです。
ツールチップを実装するには、とりあえず継承しただけである AuthoringScope
クラス内の、
GetDataTipText
を使用します。
GetDataTipText
には、 Ln, Col が渡されるので、該当位置にあるトークンを取得し、
それにあった結果を返します。
しかしながら、コードの解析を行う IScanner
には行番号が降ってこないため、
行番号が渡されるよう、次のように変更します。
まず、 Microsoft.VisualStudio.Package.Colorizer
を継承したクラスを作成します。
次に、 ColorizeLine
及び GetLineInfo
をオーバーライドし、Scanner
へと
行番号を渡すように変更します。
これらのメソッドは、内部で IScanner
の SetSource
及び ScanToken~
を呼び出しており、
また、 SetSource
及び ScanToken~
はこれらのメソッド経由で呼び出されています。
そのため、その処理の直前で行番号を渡します。
これらを実装したものが下のコード。
using System;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;
using VSLanguageService = Microsoft.VisualStudio.Package.LanguageService;
namespace HSPToolsVS.LanguageService
{
[ComVisible(true)]
internal class HSPColorizer : Colorizer
{
public HSPColorizer(VSLanguageService svc, IVsTextLines buffer, IScanner scanner) : base(svc, buffer, scanner)
{
}
#region Overrides of Colorizer
public override int ColorizeLine(int line, int length, IntPtr ptr, int state, uint[] attrs)
{
(Scanner as HSPScanner)?.SetLineNumber(line);
return base.ColorizeLine(line, length, ptr, state, attrs);
}
public override TokenInfo[] GetLineInfo(IVsTextLines buffer, int line, IVsTextColorState colorState)
{
(Scanner as HSPScanner)?.SetLineNumber(line);
return base.GetLineInfo(buffer, line, colorState);
}
#endregion
}
}
次に、上の Colorizer を使うように、 HSPLanguageService
を変更します。
public override Colorizer GetColorizer(IVsTextLines buffer)
{
return new HSPColorizer(this, buffer, GetScanner(buffer));
}
なお、 GetColorizer
はキャッシュ機構を持っているため、
本来ならばそれも実装すべきかもしれません。
あとは、 AuthoringScope
にて、トークンを元にツールチップテキストを返します。
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;
namespace HSPToolsVS.LanguageService
{
internal class HSPAuthoringScope : AuthoringScope
{
private readonly IEnumerable<Token> _tokens;
public HSPAuthoringScope(IEnumerable<Token> tokens)
{
_tokens = tokens;
}
public override string GetDataTipText(int line, int col, out TextSpan span)
{
span = new TextSpan();
var token = GetTokenFromLineAndCol(line, col);
if (token == null || token.Type == HSPTokenType.Comment || token.Type == HSPTokenType.Numeric)
return null;
span.iStartLine = line;
span.iEndLine = line;
span.iStartIndex = token.StartIndex;
span.iEndIndex = token.EndIndex;
return $"{token.Type} : {token.Text}";
}
// 略
private Token GetTokenFromLineAndCol(int line, int col)
{
return _tokens.SingleOrDefault(w => w.Line == line && w.StartIndex <= col && col <= w.EndIndex);
}
}
}
参考: