我试图用MEF为GLSL做一个简单的扩展(这也是我的第一个,我试图理解语言服务和其他东西,但我完全迷失了。看起来比较太多的工作比较给MEF一个简单的非专业的东西)。我一直在关注MSDN上的教程和OOK示例,以创建基本的语法着色,大括号匹配和IntelliSense支持。我创建了我的内容类型来扩展C / C ++,所以我有C / C ++关键字的默认颜色,但是我无法访问C / C ++ IntelliSense,完成集甚至不在列表中。有没有办法获得默认的IntelliSense以及我自己的完成集?
这是我的完成来源:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Language.Intellisense;
using System.Collections.ObjectModel;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Tagging;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Utilities;
namespace GLSL_Extension {
[Export(typeof(ICompletionSourceProvider))]
[ContentType(GLSLConstants.ContentType)]
[Name(GLSLConstants.CompletionSourceProviderName)]
class GLSLCompletionSourceProvider : ICompletionSourceProvider {
public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer) {
return new GLSLCompletionSource(textBuffer);
}
}
class GLSLCompletionSource : ICompletionSource, IDisposable {
private ITextBuffer buffer;
private bool disposed = false;
public GLSLCompletionSource(ITextBuffer buffer) {
this.buffer = buffer;
}
public void AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets) {
if (this.disposed)
throw new ObjectDisposedException(this.ToString());
List<Completion> completions = new List<Completion>(){
new Completion(GLSLCompletionResources.uniformName, GLSLCompletionResources.uniformName, GLSLCompletionResources.uniformDesc, null, ""),
new Completion(GLSLCompletionResources.varyingName, GLSLCompletionResources.varyingName, GLSLCompletionResources.varyingDesc, null, ""),
new Completion(GLSLCompletionResources.inName, GLSLCompletionResources.inName, GLSLCompletionResources.inDesc, null, ""),
new Completion(GLSLCompletionResources.outName, GLSLCompletionResources.outName, GLSLCompletionResources.outDesc, null, ""),
new Completion(GLSLCompletionResources.vec2Name, GLSLCompletionResources.vec2Name, GLSLCompletionResources.vec2Desc, null, ""),
new Completion(GLSLCompletionResources.vec3Name, GLSLCompletionResources.vec3Name, GLSLCompletionResources.vec3Desc, null, ""),
new Completion(GLSLCompletionResources.vec4Name, GLSLCompletionResources.vec4Name, GLSLCompletionResources.vec4Desc, null, ""),
new Completion(GLSLCompletionResources.mat2Name, GLSLCompletionResources.mat2Name, GLSLCompletionResources.mat2Desc, null, ""),
new Completion(GLSLCompletionResources.mat3Name, GLSLCompletionResources.mat3Name, GLSLCompletionResources.mat3Desc, null, ""),
new Completion(GLSLCompletionResources.mat4Name, GLSLCompletionResources.mat4Name, GLSLCompletionResources.mat4Desc, null, "")
};
ITextSnapshot snapshot = this.buffer.CurrentSnapshot;
var triggerPoint = (SnapshotPoint)session.GetTriggerPoint(snapshot);
if (triggerPoint == null)
return;
var line = triggerPoint.GetContainingLine();
SnapshotPoint start = triggerPoint;
while (start > line.Start && !char.IsWhiteSpace((start - 1).GetChar())) {
start -= 1;
}
var applicableTo = snapshot.CreateTrackingSpan(new SnapshotSpan(start, triggerPoint), SpanTrackingMode.EdgeInclusive);
completionSets.Add(new CompletionSet("All", "All", applicableTo, completions, Enumerable.Empty<Completion>()));
}
public void Dispose() {
if (!this.disposed) {
GC.SuppressFinalize(this);
this.disposed = true;
}
}
}
}
我的完成控制器:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.Composition;
using System.Diagnostics;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio;
using System.Windows;
using System.Runtime.InteropServices;
namespace GLSL_Extension {
[Export(typeof(IVsTextViewCreationListener))]
[ContentType(GLSLConstants.ContentType)]
[TextViewRole(PredefinedTextViewRoles.Interactive)]
internal sealed class VsTextViewCreationListener : IVsTextViewCreationListener {
[Import]
IVsEditorAdaptersFactoryService AdaptersFactory = null;
[Import]
ICompletionBroker CompletionBroker = null;
public void VsTextViewCreated(IVsTextView textViewAdapter) {
IWpfTextView view = AdaptersFactory.GetWpfTextView(textViewAdapter);
Debug.Assert(view != null);
CommandFilter filter = new CommandFilter(view, CompletionBroker);
IOleCommandTarget next;
textViewAdapter.AddCommandFilter(filter, out next);
filter.Next = next;
}
}
internal sealed class CommandFilter : IOleCommandTarget {
private ICompletionSession currentSession;
public IWpfTextView TextView { get; private set; }
public ICompletionBroker Broker { get; private set; }
public IOleCommandTarget Next { get; set; }
public CommandFilter(IWpfTextView textView, ICompletionBroker broker) {
this.currentSession = null;
TextView = textView;
Broker = broker;
}
private char GetTypeChar(IntPtr pvaIn) {
return (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
}
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
bool handled = false;
int hresult = VSConstants.S_OK;
if (pguidCmdGroup == VSConstants.VSStd2K) {
switch ((VSConstants.VSStd2KCmdID)nCmdID) {
case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
case VSConstants.VSStd2KCmdID.COMPLETEWORD:
handled = StartSession();
break;
case VSConstants.VSStd2KCmdID.RETURN:
handled = Complete(false);
break;
case VSConstants.VSStd2KCmdID.TAB:
handled = Complete(true);
break;
case VSConstants.VSStd2KCmdID.CANCEL:
handled = Cancel();
break;
}
}
if (!handled)
hresult = Next.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
if (ErrorHandler.Succeeded(hresult)) {
if (pguidCmdGroup == VSConstants.VSStd2K) {
switch ((VSConstants.VSStd2KCmdID)nCmdID) {
case VSConstants.VSStd2KCmdID.TYPECHAR:
char ch = GetTypeChar(pvaIn);
if (ch == ' ')
StartSession();
else if (this.currentSession != null)
Filter();
break;
case VSConstants.VSStd2KCmdID.BACKSPACE:
Filter();
break;
}
}
}
return hresult;
}
private void Filter() {
if (this.currentSession == null)
return;
this.currentSession.SelectedCompletionSet.SelectBestMatch();
this.currentSession.SelectedCompletionSet.Recalculate();
}
bool Cancel() {
if (this.currentSession == null)
return false;
this.currentSession.Dismiss();
return true;
}
bool Complete(bool force) {
if(this.currentSession == null)
return false;
if (!this.currentSession.SelectedCompletionSet.SelectionStatus.IsSelected && !force) {
this.currentSession.Dismiss();
return false;
} else {
this.currentSession.Commit();
return true;
}
}
bool StartSession() {
if (this.currentSession != null)
return false;
SnapshotPoint caret = TextView.Caret.Position.BufferPosition;
ITextSnapshot snapshot = caret.Snapshot;
if (!Broker.IsCompletionActive(TextView))
this.currentSession = Broker.CreateCompletionSession(TextView, snapshot.CreateTrackingPoint(caret, PointTrackingMode.Positive), true);
else
this.currentSession = Broker.GetSessions(TextView).First();
this.currentSession.Dismissed += (sender, args) => this.currentSession = null;
this.currentSession.Start();
return true;
}
public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) {
if (pguidCmdGroup == VSConstants.VSStd2K) {
switch ((VSConstants.VSStd2KCmdID)prgCmds[0].cmdID) {
case VSConstants.VSStd2KCmdID.AUTOCOMPLETE:
case VSConstants.VSStd2KCmdID.COMPLETEWORD:
prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_ENABLED | (uint)OLECMDF.OLECMDF_SUPPORTED;
return VSConstants.S_OK;
}
}
return Next.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
}
}
}