2016-03-25 2 views
2

Я разрабатываю код gen (VSIX) для своей команды, и я намерен использовать Roslyn в качестве основного движка после того, как я борюсь с инфраструктурой расширяемости VSIX.Roslyn: Получить текущий проект/Получить текущий документ, который выбран

Мой код gen в настоящее время способен генерировать новый csproj для решения и способен выводить базу шаблонных кодов на основе проекта Templating из расширяемости VSIX. Поскольку я амбициозен, я стараюсь не полагаться на статический шаблонный проект и использовать Roslyn, чтобы вместо этого использовать код.

У моего решения есть список папок, и каждая папка имеет список csproj.

Мой вопрос 1 Я пытаюсь использовать API-интерфейс Roslyn Workspace для обнаружения текущего документа (.cs), который был открыт в редакторе кода, или я пытаюсь получить текущий идентификатор документа выбранного файла cs, который я делаю правой кнопкой мыши из проводника решений.

Я попытался использовать AdhocWorkspace, которое до сих пор провалилось, поскольку я не могу его получить.

Вопрос 2. Если я должен использовать AdhocWorkspace, могу ли я изменить пространство имен по умолчанию в свойствах csproj? Или это не было частью функциональности в API Roslyn Workspace на данный момент?

Спасибо.

+1

Предполагая, что вы используете VS2015, вы должны использовать [ 'VisualStudioWorkspace'] (https://joshvarty.wordpress.com/2014/09/12/learn-roslyn-now-part-6- работоспособного с-рабочими пространствами /). Это то, что использует VS под капотом. Вы можете использовать ['GetOpenDocumentIds()'] (http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Workspace/Workspace_Editor.cs,356559a2f4bb0d36). Вы также должны учитывать, что сразу можно открыть несколько документов. (например, сплит-панели) – JoshVarty

+0

@JoshVarty: не поддерживает ли API API неактивные вкладки? – SLaks

+1

Да, да. Нет понятия «последняя открытая вкладка» на уровне рабочей области (насколько я могу судить), поэтому, вероятно, требуется ['GetOpenDocumentInCurrentContext'] (http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Workspace/ TextExtensions.cs, 7d8ce0f29a31ba83). 'SourceTextContainer' можно найти из' IWpfTextView' или 'ITextBuffer' через: http://source.roslyn.io/#Microsoft.CodeAnalysis.EditorFeatures.Text/Extensions.cs – JoshVarty

ответ

0

Для # 1 некоторого кода я должен сделать то же самое. Я делаю вещи с помощью курсора, поэтому я просматриваю caretPosition (курсор). Есть и другие способы, но суть одна и та же, получить текущее текстовое представление от этого до Roslyn.

private IVsEditorAdaptersFactoryService GetEditorAdaptersFactoryService() 
    { 
     IComponentModel componentModel =(IComponentModel)GetService(typeof(SComponentModel)); 
     return componentModel.GetService<IVsEditorAdaptersFactoryService>(); 
    } 
private Microsoft.VisualStudio.Text.Editor.IWpfTextView GetTextView() 
{ 
    IVsTextManager textManager = (IVsTextManager)GetService(typeof(SVsTextManager)); 
    if (textManager == null) 
     return null; 
    IVsTextView textView = null; 
    textManager.GetActiveView(1, null, out textView); 
    if (textView == null) 
     return null; 
    return GetEditorAdaptersFactoryService().GetWpfTextView(textView); 
} 

//code to get the doc 
Microsoft.VisualStudio.Text.Editor.IWpfTextView textView = GetTextView(); 
if (textView != null) 
{ 
    SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; 
    Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); 
//do stuff with Roslyn Document 
} 

«или я пытаюсь получить текущий идентификатор документа выбранного файла cs, который я нажимаю правой кнопкой мыши из проводника решений».

Это действительно уродливое, но то, что я использовал из другого сообщения SO (не помню автора), которое действительно работает.

private static bool IsSingleProjectItemSelection(out IVsHierarchy hierarchy, out uint itemid) 
    { 
     hierarchy = null; 
     itemid = VSConstants.VSITEMID_NIL; 
     int hr = VSConstants.S_OK; 

     var monitorSelection = Package.GetGlobalService(typeof(SVsShellMonitorSelection)) as IVsMonitorSelection; 
     var solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution; 
     if (monitorSelection == null || solution == null) 
      return false; 

     IVsMultiItemSelect multiItemSelect = null; 
     IntPtr hierarchyPtr = IntPtr.Zero; 
     IntPtr selectionContainerPtr = IntPtr.Zero; 

     try 
     { 
      hr = monitorSelection.GetCurrentSelection(out hierarchyPtr, out itemid, out multiItemSelect, out selectionContainerPtr); 
      if (ErrorHandler.Failed(hr) || hierarchyPtr == IntPtr.Zero || itemid == VSConstants.VSITEMID_NIL) 
       return false; 
      // multiple items are selected 
      if (multiItemSelect != null) 
       return false; 
      // there is a hierarchy root node selected, thus it is not a single item inside a project 
      if (itemid == VSConstants.VSITEMID_ROOT) 
       return false; 

      hierarchy = Marshal.GetObjectForIUnknown(hierarchyPtr) as IVsHierarchy; 
      if (hierarchy == null) 
       return false; 

      Guid guidProjectID = Guid.Empty; 

      if (ErrorHandler.Failed(solution.GetGuidOfProject(hierarchy, out guidProjectID))) 
       return false; 

      // if we got this far then there is a single project item selected 
      return true; 
     } 
     finally 
     { 
      if (selectionContainerPtr != IntPtr.Zero) 
       Marshal.Release(selectionContainerPtr); 

      if (hierarchyPtr != IntPtr.Zero) 
       Marshal.Release(hierarchyPtr); 
     } 
    } 

IVsHierarchy hierarchy = null; 
       uint itemid = VSConstants.VSITEMID_NIL; 
       if (!IsSingleProjectItemSelection(out hierarchy, out itemid)) 
        return; 
       string itemFullPath = null; 
       ((IVsProject)hierarchy).GetMkDocument(itemid, out itemFullPath); 
       if (itemFullPath.EndsWith(".cs")) 
+0

Похож на потенциальное решение для меня. Я попробую. Будет ли проблема, если решение будет иметь большое количество проектов? Эффективность? –

+0

Поскольку он начинается с курсора и работает в проекте, не имеет значения, сколько проектов существует, но это зависит от того, как работает API под ним, поэтому я не могу сказать, что обещаю. –

Смежные вопросы