c# - How do you use a projection buffer to support embedded languages in the Visual Studio editor -
at end of first paragraph in link states:
the visual studio text outlining feature implemented using projection buffer hide collapsed text, , the visual studio editor asp.net pages uses projection support embedded languages such visual basic , c#.
i have searched , searched have not found examples or documentation @ accomplish this, have idea how done? have gotten classification working , created projection buffer of spans want classified c# code. set buffers context type "csharp" spans never classified. have tried base content type "projection" work either.
i've managed embed projection buffers in tool window , hook them c#'s language services. 1 caveat: approach works visual studio using roslyn. i've published github project can use accompanying blog post.
the answer question long , involves many moving pieces doesn't lend stackoverflow style of q&a well. being said, i'll summarize necessary steps , include relevant code.
the following sample creates projection buffer of file comprised of first 100 characters of file.
we first create ivsinvisibleeditor
given filepath , create code window it. set contents of code window ivstextlines
of ivsinvisibleeditor
.
we set custom role "customprojectionrole"
on text buffer of code window. role allows customize text buffer via mef exported itextviewmodelprovider
.
public iwpftextviewhost createeditor(string filepath, int start = 0, int end = 100) { //ivsinvisibleeditors in-memory represenations of typical visual studio editors. //language services, highlighting , error squiggles hooked these editors //for once convert them wpftextviews. var invisibleeditor = getinvisibleeditor(filepath); var docdatapointer = intptr.zero; guid guidivstextlines = typeof(ivstextlines).guid; errorhandler.throwonfailure(invisibleeditor.getdocdata( fensurewritable: 1 , riid: ref guidivstextlines , ppdocdata: out docdatapointer)); ivstextlines docdata = (ivstextlines)marshal.getobjectforiunknown(docdatapointer); //create code window adapter var codewindow = _editoradapter.createvscodewindowadapter(visualstudioservices.oleserviceprovider); errorhandler.throwonfailure(codewindow.setbuffer(docdata)); //get text view our editor use wpf control editor. ivstextview textview; errorhandler.throwonfailure(codewindow.getprimaryview(out textview)); //we add our own role text view. later allow selectively modify //this editor without getting in way of visual studio's normal editors. var roles = _editorfactoryservice.defaultroles.concat(new string[] { "customprojectionrole" }); var vstextbuffer = docdata ivstextbuffer; var textbuffer = _editoradapter.getdatabuffer(vstextbuffer); textbuffer.properties.addproperty("startposition", start); textbuffer.properties.addproperty("endposition", end); var guid = vsconstants.vstextbufferuserdataguid.vstextviewroles_guid; ((ivsuserdata)codewindow).setdata(ref guid, _editorfactoryservice.createtextviewroleset(roles).tostring()); _currentlyfocusedtextview = textview; var textviewhost = _editoradapter.getwpftextviewhost(textview); return textviewhost; }
we create ivstextviewmodelprovider
creates , returns projectiontextviewmodel
. projectiontextviewmodel
saves projection buffer within visual buffer. means when buffer displayed, projection buffer shown. however, language services of backing data buffer operate correctly.
[export(typeof(itextviewmodelprovider)), contenttype("csharp"), textviewrole("customprojectionrole")] internal class projectiontextviewmodelprovider : itextviewmodelprovider { public itextviewmodel createtextviewmodel(itextdatamodel datamodel, itextviewroleset roles) { //create projection buffer based on specified start , end position. var projectionbuffer = createprojectionbuffer(datamodel); //display projection buffer in visual buffer, while still maintaining //the full file buffer underlying data buffer. var textviewmodel = new projectiontextviewmodel(datamodel, projectionbuffer); return textviewmodel; } public iprojectionbuffer createprojectionbuffer(itextdatamodel datamodel) { //retrieve start , end position saved in mytoolwindow.createeditor() var startposition = (int)datamodel.databuffer.properties.getproperty("startposition"); var endposition = (int)datamodel.databuffer.properties.getproperty("endposition"); var length = endposition - startposition; //take snapshot of text within these indices. var textsnapshot = datamodel.databuffer.currentsnapshot; var trackingspan = textsnapshot.createtrackingspan(startposition, length, spantrackingmode.edgeexclusive); //create actual projection buffer var projectionbuffer = projectionbufferfactory.createprojectionbuffer( null , new list<object>() { trackingspan } , projectionbufferoptions.none ); return projectionbuffer; } [import] public iprojectionbufferfactoryservice projectionbufferfactory { get; set; } }
hopefully gets future visitors off start.
Comments
Post a Comment