IArguments and IArgument

2 posts, 0 answers
  1. Jim
    Jim avatar
    4 posts
    Member since:
    May 2012

    Posted 14 Mar 2013 Link to this post

    Good Morning, Everyone.

    I am working on a new JustCode analysis rule.  I query for a particular IMethodInvocation that has a specific identifier. 

    foreach (IMethodInvocation mi in fileModel.All<IMethodInvocation>().Where(m => m.Identifier.Text == "IsNumeric"))

    In the object "mi", There is an Arguments Collection(?). Under there is another Arguments Collection(again ?). I am having problems finding the particular IArgument object (there's only 1 argument for IsNumeric in VB). 

    I have tried everything that I can think of to access the IArgument in IArguments[].  However, I usually get something about cannot convert a #2W.#xZ as an IArgument.  Here is my latest try that failed miserably!

    foreach (var arg in args.ToEnumerable<IArguments>())
        IMemberAccess ma = (IArgument)arg.Expression;
        if ((IArgument)arg.Expression.Type.Name.ToUpper() == "STRING")
            mi.AddCodeMarker(Constants.EM110WarningExampleID, this, Constants.EM110FixText);

    Can someone please post some sample code on how to iterate through the collection of Arguments so that I may evaluate each one (in this case, one)?  When I do a "QuickWatch", I get this expression when I drill down into the Argument itself...

    (new System.Linq.SystemCore_EnumerableDebugView<Telerik.JustCode.CommonLanguageModel.IArgument>(mi.Arguments.Arguments as #2W.#xZ<Telerik.JustCode.CommonLanguageModel.IArgument>))).Items[0])

    Any help is greatly appreciated!


    Jim Evans
    Application Architect




  2. Ivan
    Ivan avatar
    106 posts

    Posted 14 Mar 2013 Link to this post


    Thank you for your feedback.
    Each IMethodInvocation has an IArguments property. The "IArguments" type holds the arguments collection. So if you want to iterate over the arguments of a method invocation you need:
    foreach (IMethodInvocation methodInvocation in fileModel.All<IMethodInvocation>())
        foreach (IArgument argument in methodInvocation.Arguments.Arguments)

    There is also no need for you to cast the expression of an argument. You can directly access its type:
    var expressionType = argument.Expression.Type;
    bool isStringType = expressionType.Equals(argument.StringTypeAtThisLocation());
    "StringTypeAtThisLocation" return the "String" type for the current language (this way your extension can work for any language that has "string" as a type.
    I also noticed the way that you try to cast constructs. We recommend to use the JC API in order to cast one construct to another.
    For example
    var expression = argument.Expression.As<IArgument>();
    bool isArgument = argument.Expression.Is<IArgument>();
    These methods never throw exceptions and the "As<>" method never returns null so that you will not need to do any null checks. If the cast fails we simply return a proxy object (a stub) that has the default behavior for the given type. And this way the execution of your code will continue without any exceptions.
    Another thing that I would like to suggest is to use IConstructLanguage.AreNamesEqual method. This method knows whether the language is case sensitive or not and does the correct check. For instance:
    foreach (IMethodInvocation methodInvocation in fileModel.All<IMethodInvocation>().Where(x => x.Language.AreNamesEqual(x.Identifier.Name, "IsNumeric")))
    Please note that I also use x.Identifier.Name, not x.Identifier.Text. Although, they both return the same thing, the "Name" property is much more faster.

    If you have any more questions or remarks, please do not hesitate to contact us again!

    the Telerik team
    Share what you think about JustCode with us, so we can help you even better! You can use the built-in feedback tool inside JustCode, our forum, or our JustCode feedback portal.
  3. DevCraft R3 2016 release webinar banner
Back to Top