views:

48

answers:

1

I've spent some time trying to find a way CodeRush could add using when it finds undeclared element that is in the fact class name with no using added. The solution suggested in this answer to my question (Refactor_resolve) does not work (bugged?).

In a process I found out that writing plug-ins for CodeRush is easy, so I decided to code this functionality myself (and share it). I'd only implement a CodeProvider (like in this tutorial). The only thinks I need to do the job are answers to this questions:

  1. At the start up of my plugin I need to get a list (set, map, whatever) of all classes and their packages. This means all the classes(interfaces...) and their packages in project, and within all referenced libraries. And I also need to receive updated on this (when user adds reference, creates new class). Can I get this from some CodeRush classes or maybe VS interface available from CodeProvider class?

  2. How do I add created CodeProvider to the pop-up that is shown when user hovers over an Issue?

+2  A: 

BTW, it looks like Rory has fixed some bugs in the "Refactor_Resolver" plug-in and it works now. As for your questions here's a quick reply:

RE #1:

CodeRush has a built-in cache for all types, project references, etc that is built while the solution is parsing. But at the moment it is used internally and not exposed for plug-in devs, sorry. However, here are some useful APIs to get started with:

  // Using the source code cache...

  // gets the active Solution object
  SolutionElement activeSolution = CodeRush.Source.ActiveSolution;
  if (activeSolution == null)
    return;

  // iterate thought all projects in the solution
  foreach (ProjectElement project in activeSolution.AllProjects)
  {
    string assemblyName = project.AssemblyName;

    // iterate inside source code symbols cache...
    Hashtable projectSymbols = activeProject.ProjectSymbols;
    foreach (object item in projectSymbols.Values)
    {
      ITypeElement typeElement = item as ITypeElement;
      if (typeElement == null)
        continue;

      // TODO: ...
    }
  }

To get assembly references cache, use a ScopeManager (located in DevExpress.DXCore.MetaData.dll), e.g.

  IEnumerable<IMetaDataScope> allMetaDataScopes = ScopeManager.All;
  foreach (IMetaDataScope scope in allMetaDataScopes)
  {
    IAssemblyInfo assembly = scope.Assembly;
    if (assembly != null)
    {
      ITypeInfo[] types = assembly.GetTypes();
      for (int i = 0; i < types.Length; i++)
      {
        ITypeInfo typeInfo = types[i];
        if (typeInfo == null)
          continue;

        // TODO: ...
      }
    }
  }

RE #2: To add a CodeProvider to the pop-up set its "CodeIssueMessage" property to the name of the code issue to fix, e.g.

myCodeProvider.CodeIssueMessage = "Undeclared element";

Let me know if you need further assistance.

Alex Skorkin
Great answer! Thank you. Your code allows be to build plugin's internal cache when the plugin is loaded. Of cause it would be much simpler then the CodeRush's cache - it would only contain a `String` for each object(`Class`, `Interface`... ) that can be referenced from within project classes. However this may be long running task. It is suitable to run at the plugin start up but I cannot scan all available classes each time code provider is used. It would be nice if I could register to some events that informs me about new(or deleted) classes or references so I don't have to rescan.
drasto