Private methods accessed by VisitMethodEntry?

I have a class with lots of methods and properties.

I have a rule that logs when each method in my class is visited by FxCop's VisitMethodEntry and VisitCall methods.

What I fail to understand is why FxCop appears to visit some, but not all, of the methods in my class. I guess I'm suffering from a fundamental misunderstanding of how this is meant to work. Can someone put me straight

Kind regards,
Angus

Debugging rule:

internal abstract class UsageControlFlowRule : BaseControlFlowRule
{
protected UsageControlFlowRule(string name)
: base(name, "Microsoft.FxCop.Rules.XsoEnforcement.EnforcementIntrospectionRules.xml", typeof(EnforcementIntrospectionRule).Assembly)
{}
}

sealed
internal class DebugRule : UsageControlFlowRule
{
static DebugRule()
{
string debugFile = Path.Combine(
System.Environment.GetEnvironmentVariable("INETROOT"),
@"sources\tools\Common\src\FxCop\XsoEnforcementRules\fxcopdebugrule.txt");
DebugRule.debugStream = new FileStream(debugFile, FileMode.Create);
DebugRule.debug = new StreamWriter(debugStream);
}

public DebugRule()
: base("DebugRule")
{}

public override void VisitCall(
Variable destination,
Variable receiver,
Method callee,
ExpressionList arguments,
bool isVirtualCall,
IProgramContext programContext,
IExecutionState stateBeforeInstruction,
IExecutionState stateAfterInstruction)
{
DebugRule.debug.WriteLine(
"VisitCall: {0}\r\n\tcalls: {1}",
RuleUtilities.Format(base.CurrentMethod),
RuleUtilities.Format(callee));
DebugRule.debug.Flush();
}

public override void VisitCopy(
Variable destination,
Variable source,
IProgramContext programContext,
IExecutionState stateBeforeInstruction,
IExecutionState stateAfterInstruction)
{}

public override void VisitMethodEntry(
Method method,
IEnumerable parameters,
IProgramContext programContext,
IExecutionState stateBeforeInstruction,
IExecutionState stateAfterInstruction)
{
base.CurrentMethod = method;
DebugRule.debug.WriteLine("VisitMethodEntry: {0}", RuleUtilities.Format(base.CurrentMethod));
DebugRule.debug.Flush();
}

public override TargetVisibilities TargetVisibility
{
get
{
return TargetVisibilities.All;
}
}

private static Stream debugStream;
private static StreamWriter debug;
}

Snippet of class to be analyzed:

internal sealed class MailboxSession : StoreSession
{
private MailboxSession(CultureInfo cultureInfo, string clientInfoString);

public static MailboxSession Open(
ExchangePrincipal mailboxOwner,
WindowsPrincipal authenticatedUser,
CultureInfo cultureInfo,
string clientInfoString);

public static MailboxSession Open(
ExchangePrincipal mailboxOwner,
IntPtr authenticatedUserHandle,
CultureInfo cultureInfo,
string clientInfoString);

public static MailboxSession OpenAsAdmin(
ExchangePrincipal mailboxOwner,
CultureInfo cultureInfo,
string clientInfoString);

public static MailboxSession OpenAsAdmin(
ExchangePrincipal mailboxOwner,
CultureInfo cultureInfo,
string clientInfoString,
bool useLocalRpc);

...
}

Example of output logged by VisitMethodEntry. The important point is that the two MailboxSession.Open methods aren't invoked yet the essentially similar MailboxSession.OpenAsAdmin methods are:

VisitMethodEntry: MailboxSession.get_UserConfigurationManager():UserConfigurationManager
VisitMethodEntry: MailboxSession.get___ContainedMapiStore():MapiStore
VisitMethodEntry: MailboxSession.get_TimeZone():ExchangeTimeZone
VisitMethodEntry: MailboxSession.set_TimeZone(ExchangeTimeZone):Void
VisitMethodEntry: MailboxSession.get_InboxRules():Rules
VisitMethodEntry: MailboxSession.get_JunkEmailRule():JunkEmailRule
VisitMethodEntry: MailboxSession.get_DelegateUser():ADOrgPerson
VisitMethodEntry: MailboxSession.get_MailboxOwnerLegacyDN():String
VisitMethodEntry: MailboxSession.get_MailboxOwner():ExchangePrincipal
VisitMethodEntry: MailboxSession.get_DisplayName():String
VisitMethodEntry: MailboxSession.get_FullyQualifiedServerName():String
VisitMethodEntry: MailboxSession.get_InternalMailboxOwner():ExchangePrincipal
VisitMethodEntry: MailboxSession.get_SubscriptionCount():Int32
VisitMethodEntry: MailboxSession.set_SubscriptionCount(Int32):Void
VisitMethodEntry: MailboxSession.get_FilterPrivateItems():Boolean
VisitMethodEntry: MailboxSession.MailboxSession(CultureInfo, String)
VisitMethodEntry: MailboxSession.CreateAlternateMailboxSession(StoreSession, ExchangePrincipal):MailboxSession
VisitMethodEntry: MailboxSession.OpenAsAdmin(ExchangePrincipal, CultureInfo, String):MailboxSession
VisitMethodEntry: MailboxSession.OpenAsAdmin(ExchangePrincipal, CultureInfo, String, Boolean):MailboxSession
VisitMethodEntry: MailboxSession.OpenAsTransport(ExchangePrincipal):MailboxSession
VisitMethodEntry: MailboxSession.CreateMailboxSession(LogonType, ExchangePrincipal, ADOrgPerson, Object, OpenMailboxSessionFlags, CultureInfo, String):MailboxSession
VisitMethodEntry: MailboxSession.CreateDefaultFolder(DefaultFolderType):StoreObjectId
VisitMethodEntry: MailboxSession.DeleteDefaultFolder(DefaultFolderType, DeleteItemFlags):Void
VisitMethodEntry: MailboxSession.LocalizeDefaultFolders(Exception[]&):OperationResult
VisitMethodEntry: MailboxSession.VerifyDefaultFolderLocalization():Boolean
VisitMethodEntry: MailboxSession.GetJunkEmailRuleStatus():JunkEmailStatus
VisitMethodEntry: MailboxSession.GetMasterCategoryList():MasterCategoryList
VisitMethodEntry: MailboxSession.InternalDispose(Boolean):Void
VisitMethodEntry: MailboxSession.InternalGetMasterCategoryList():MasterCategoryList
VisitMethodEntry: MailboxSession.InternalIsConfigurationFolder(StoreObjectId):Boolean
VisitMethodEntry: MailboxSession.InternalGetSupportedRoutingTypes():String[]
VisitMethodEntry: MailboxSession.InternalInitializeDefaultFolders():Void
VisitMethodEntry: MailboxSession.EnableUserTracing():Void
VisitMethodEntry: MailboxSession.DisableUserTracing():Void
VisitMethodEntry: MailboxSession.MailboxSession(MapiStore, CultureInfo)
VisitMethodEntry: MailboxSession.InitializeDefaultFolders():Void
VisitMethodEntry: MailboxSession.GetItemFromMapiMessageForContentConversion(MapiMessage, MapiStore, String, Boolean):MessageItem



Answer this question

Private methods accessed by VisitMethodEntry?

  • Peter Cheesewright

    Angus,

    As Michael mentioned above, the API you are using will no longer exist in future versions of FxCop and Visual Studio.

    At the moment there is no officially supported custom rules API, it is all considered an off-road experience.

    If you would like to discuss things further, don't hesistate to contact me personally (alias: davkean).

    Regards

    David



  • i-code-4-fun

    Hi, Michael,

    Thanks for answering my questions. To answer yours:

    I want to verify that our (Exchange’s XSO component) format strings are valid. The things passed to String.Format, but also a heap of other tracing APIs of our own. I found FxCop’s ProvideCorrectArgumentsToFormattingMethods rule which uses this visitor pattern, so thought I’d adapt it to my own use. A couple of examples:

    // ProvideCorrectArgumentsToFormattingMethods will warn that I’m not providing

    // an argument for the format specifier.

    String.Format(“foo {0}”);

    // ProvideCorrectArgumentsToFormattingMethods will warn that I’m not providing

    // a format specifer for an argument.

    String.Format(“foo {0}”, 1, 2);

    Again, I emphasize that the rule works well and I’ve extended it for my own use to cover XSO’s tracing APIs. However, tests show that FxCop hits only about 280 of the 480 String.Format calls in our code.

    Here’s how Reflector displays the class I’ve been examining. Notice that the OpenAsAdmin and Open methods have essentially similar interfaces. FxCop’s VisitMethodCall visits the OpenAsAdmin methods but not the Open methods.

    internal sealed class MailboxSession : StoreSession
    {
    private MailboxSession(MapiStore store, CultureInfo cultureInfo);
    private MailboxSession(CultureInfo cultureInfo, string clientInfoString);

          internal static MailboxSession Open(ExchangePrincipal mailboxOwner, ClientSecurityContext clientSecurityContext, CultureInfo cultureInfo, string clientInfoString);
    public static MailboxSession Open(ExchangePrincipal mailboxOwner, IntPtr authenticatedUserHandle, CultureInfo cultureInfo, string clientInfoString);
    public static MailboxSession Open(ExchangePrincipal mailboxOwner, WindowsPrincipal authenticatedUser, CultureInfo cultureInfo, string clientInfoString);




    public static MailboxSession OpenAsAdmin(ExchangePrincipal mailboxOwner, CultureInfo cultureInfo, string clientInfoString);
    public static MailboxSession OpenAsAdmin(ExchangePrincipal mailboxOwner, CultureInfo cultureInfo, string clientInfoString, bool useLocalRpc);

    }

    So, I guess my question becomes, what’s the “supported” way to go about ensuring that our use of format strings is correct (How do I discover what’s supported and what’s not supported ) There doesn’t appear to be any documentation, so I’ve been wandering around in the dark a little ;-)

    Regards (and nice to make contact ;-))

    Angus


  • SureshGubba

    Hi, Angus,

    You've entered into an entirely unsupported area of FxCop custom rules development. Our control flow functionality hasn't been finalized (in fact, the flow analysis in 1.35 doesn't exist anymore in the current builds).

    I couldn't say offhand why your trace isn't getting hit for the methods in question. Is there anything interesting about your Open methods Are they abstract, for instance

    If you wanted to chase this down, I'd need to get a repro from you. It might be helpful to understand the kind of analysis you're trying to build, though. If you don't need to use this unsupported functionality to accomplish what you're after, it might not be worth investigating further.



  • Private methods accessed by VisitMethodEntry?