Skip to content

Internal Codebase Analysis

bclothier edited this page Aug 11, 2018 · 1 revision

Because the Rubberduck project has grown into a complex project and has demanding requirements for COM interop, it is necessary to perform an internal analysis of the codebase to assist in maintaining the quality and catching any potential issues that may not be apparent. This is the purpose of the RubberduckCodeAnalysis project. It is a Roslyn code analyzer. Because it's for internal use, it is not installed in the typical fashion as other Roslyn code analyzers. Instead, each Rubberduck.*** project references the RubberduckCodeAnalysis under the Analyzers:

image

Due to the nature of reference, the RubberduckCodeAnalysis will always build as Release, even if the rest of the solution is built using Debug configuration, as shown:

image

This ensures that the code analysis will be run at all times, during the development and as part of the release build, using the same release version of the Roslyn code analyzer. All projects that starts with Rubberduck.*** should have the code analyzer referenced to ensure that its codebase is inspected, even if the project doesn't contain any user-facing code or interact with external components. This provides a guard against unexpected use of the code in those projects.

At the time of writing, the code analyzer has 5 rules implemented; all to do with COM interop:

  1. MissingGuid: Ensures that all COM-visible types have a Guid attribute.
  2. MissingClassInterface: Ensures that all COM-visible classes has a ClassInterface attribute referencing a constant from RubberduckGuid.
  3. MissingProgId: Ensures that all COM-visible classes has a ProgId attribute referencing a constant from RubberduckProgIds.
  4. MissingComDefaultInterface: Ensures that all COM-visible classes has a ComDefaultInterface attribute defined to explicitly identify its default interface.
  5. MissingInterfaceType: Ensures that all COM-visible interfaces has a InterfaceType attribute, typically set to either Dual or IDispatch.

Coming soon:

  1. Chained Wrapper Access: Ensures that we do not introduce a chained member access for any types that derives from ISafeComWrapper which can cause leaks. As an example, the below would leak the Child object:
var name =Parent.Child.Name

Instead, we prefer:

string name;
using(var child = Parent.Child)
{
   name = child.Name;
}

to ensure proper disposal of the SafeComWrapper objects.

Clone this wiki locally