Inspect and export results programmatically

Hi there,

I would like to trigger code inspection and then export its' results from code. Is there any way to do it?

Best regards

8 comments
Comment actions Permalink

Hi there! First of all, you need to collect the files you’re going to analyze:

var visitor = new CollectFilesVisitor(DaemonExcludedFilesManager.GetInstance(solution), false);
foreach (IProjectModelElement element in scope)
   element.Accept(visitor);

Next, you need to collect the inspection results for these files:

var issues = new List<IIssue>();
var rc = CollectInspectionResults.Do(solution, visitor.Files,
   SimpleTaskExecutor.Instance, x => { lock (issues) issues.Add(x); });

Finally, you need to use

IssuesReportWriter
to write the report to the path of your choice:
var stream = new FileStream(⋮); // can also use e.g. MemoryStream
solution.GetComponent<IssuesReportWriter>().WriteReport(stream, basePath, new[] { solution }, issues, new Version());

Hope this helps,
Dmitri Nesteruk

0
Comment actions Permalink

Will this code work in every solution? Or just a resharper plugin?
What references do I need?
Can't find the correct reference for: CollectFilesVisitor

0
Comment actions Permalink

Can this be done outside of a plugin? I.e. is it possible to load a solution in a command line app (for instance) and then use CollectInspectionResults.Do to run analysis?

0
Comment actions Permalink

Yes, sorry about that — seems like CollectFilesVisitor lives in tests, so it never made it to a public assembly. Here is what it looks like:

public class CollectFilesVisitor : RecursiveProjectVisitor
{
   private readonly List<IProjectFile> myFiles = new List<IProjectFile>();
   public List<IProjectFile> Files
   {
     get { return myFiles; }
   }
   public override void VisitProjectFile(IProjectFile projectFile)
   {
     if (!projectFile.IsGeneratedFile()
       && projectFile.ToSourceFiles().SelectMany(file => file.GetLanguageSpecificDaemonBehaviors())
          .Any(behavior => behavior.RunInSolutionAnalysis))
     {
       myFiles.Add(projectFile);
     }
   }
}

The code I presented works in test so it should work just fine in a standalone application. I beleive we have TeamCity using this mechanism to present ReSharper analyses.

0
Comment actions Permalink

Yes, it's definitely possible.

0
Comment actions Permalink

Thanks for the CollectFilesVisitor code. I can compile this but it doesn't have a constructor that accepts a DaemonExcludedFilesManager as in your code above.

The next issue I have is getting an ISolution. I've seen some samples for getting this from an IDataContext but this seems to be passed in to a plugin. How can I load a solution file to start using the rest of your sample above? Is there a way to do this, or to constuct an IDataContext that can do it?

0
Comment actions Permalink

Hello,

I have the same problem, I don't know how to get an ISolution object, I tried the following code :

var solution = Shell.Instance.GetComponent<ISolution>();

but it raises an exception ("There is no Application Shell running.")

Another example gets the Solution from IDataContext :

var solution = context.GetData(JetBrains.ProjectModel.DataContext.DataConstants.SOLUTION);

But I don't know how to get the context object.

Thanks

0
Comment actions Permalink

Hi Jean-Baptiste, I'm assuming you're doing this from within a plugin, in which case you have a couple of options. The usual (and recommended) way is to simply specify ISolution as a parameter to the constructor of your component. When ReSharper instantiates the components of your plugin, it will inject the current ISolution in for you. However, you need to tell ReSharper about your components, and you do that with attributes. You can use the simple [ShellComponent] or [SolutionComponent] attributes. This means the class is instantiated when ReSharper starts up (ShellComponent), or when a solution is created (SolutionComponent). Since you're after an instance of ISolution, you would need to use [SolutionComponent] - if you try to use [ShellComponent], ReSharper will throw an exception, because ISolution isn't available at this point.

Depending on what you're trying to do, you might not be need to use [SolutionComponent] - if you're writing a plugin that requires your component to have a different attribute, then you probably won't need to add anything, and using ISolution as a constructor parameter will just work (for example, if you're writing an Element Problem Analyzer, that requires the ElementProblemAnalyzerAttribute, which actually derives from SolutionComponent)

Calling Shell.Instance.GetComponent<>() is deprecated in favour of using constructor injection wherever possible (there are some subsystems that don't yet support constructor injection). And IDataContext is used in various other subsystems, such as Action Handlers. But there are a couple of other ways of getting ISolution - if you have a project model element, such as IProject, or a node in the PSI tree of a file, such as IMethodDeclaration, there is a GetSolution extension method that will return an ISolution.

Thanks
Matt

0

Please sign in to leave a comment.