I want to fire on the naming of a local, however, whenever I pass the local to the Problem constructor, the source information for the method is always used. How do I get FxCop/Code Analysis to use the source information for the local instead?

Because the declaration of a local is not associated with an executable instruction, a local does not contain any source information within the pdb. However, any usages of the local (such as an assignment) does.

The following example shows when source information is provided and not provided:

    public void Bar()
    {
        int value1;                // Does not have source information
       
value1 = 10;               // Has source information
       
int value2 = 20;           // Has source information

       
Console.WriteLine(value1); // Has source information
       
Console.WriteLine(value2); // Has source information
   
}

As most locals are assigned at their time of declaration (such as in the case of value2 in the above example), a simple trick is use the source context of the first usage of the local in place of its declaration. This works in most situations.

The following example shows this (using the code from FAQ: How do I access the locals of a method in a custom rules?):

    public override ProblemCollection Check(Member member)
    {
        Method method = member as Method
;
        if (method == null
)
            return null;

        if (method.Instructions.Length == 0)
           
return null;

        LocalList locals = method.Instructions[0].Value as LocalList;
       
if (locals == null)
           
return null;

        for (int i = 0; i < locals.Length; i++)
        {
            Local
local = locals[i];

            
if
(someCondition)
            {   // Fire on the local

                
Resolution resolution = new Resolution("Fix local {0}", local.Name.Name);

                SourceContext sourceContext = FindSourceContext(local, method.Instructions);

                Problem problem = new Problem(resolution, sourceContext);
                Problems.Add(problem);
             }
        }

        return Problems;
    }

    private static SourceContext FindSourceContext(Local local, InstructionList instructions)
    {
       
foreach (Instruction instruction in
instructions)
        {
            if
(instruction.Value == local)
            {   // Found its first usage
               
return
instruction.SourceContext;
            }
        }

       
return new SourceContext
();
    }

Note: If the local is only declared and is never assigned to, or its usage is only as the argument for an out parameter, then the source context of the method will be used.