Example #1
0
        /// <summary>
        /// Removes the members when given <see cref="cgMember"/> is present
        /// within this instance.
        /// </summary>
        /// <returns>The number of members removed</returns>
        public int RemoveCgMember(CgMember cgMember)
        {
            if (cgMember == null)
            {
                return(0);
            }
            var count = 0;

            var listsOf = new List <List <CgMember> > {
                Methods, Properties, Fields, Events
            };

            foreach (var list in listsOf)
            {
                for (var i = 0; i < list.Count; i++)
                {
                    var cgMem = list[i];
                    if (cgMem == null || !cgMember.Equals(cgMem))
                    {
                        continue;
                    }

                    if (list.Remove(cgMem))
                    {
                        count += 1;
                    }
                }
            }
            return(count);
        }
Example #2
0
        /// <summary>
        /// Returns string specific to graph-viz (ver. 2.38+)
        /// see [http://www.graphviz.org/]
        /// </summary>
        /// <returns></returns>
        public static string ToGraphVizString(this CgMember cgMem)
        {
            var graphViz = new StringBuilder();

            graphViz.Append("<tr><td align=\"left\">");
            graphViz.Append(cgMem.Name);
            graphViz.Append(" ");
            var typeColor = Etc.ValueTypesList.Contains(NfReflect.GetLastTypeNameFromArrayAndGeneric(cgMem.TypeName.Trim(), "<")) ? "blue" : "grey";

            if (cgMem.HasGetter || cgMem.HasSetter)
            {
                graphViz.Append("(");
                graphViz.Append(string.Join(", ", cgMem.Args.Select(x => x.ToGraphVizString())));
                graphViz.Append(")");
            }
            graphViz.Append(": <font color=\"");
            graphViz.Append(typeColor);
            graphViz.Append("\">");
            graphViz.Append(NfReflect.GetLastTypeNameFromArrayAndGeneric(cgMem.TypeName, "<"));
            if (cgMem.IsEnumerableType)
            {
                graphViz.Append("[*]");
            }
            graphViz.Append("</font></td></tr>");
            return(graphViz.ToString());
        }
Example #3
0
        /// <summary>
        /// Gets a constructor as a code gen member type
        /// </summary>
        /// <param name="ci"></param>
        /// <param name="typeName"></param>
        /// <param name="getCallvirtMetadataTokens"></param>
        /// <returns></returns>
        public static CgMember GetAsCgMember(ConstructorInfo ci, string typeName, bool getCallvirtMetadataTokens = false)
        {
            if (ci == null || string.IsNullOrWhiteSpace(typeName))
            {
                return(null);
            }

            var cgMem = new CgMember
            {
                Name          = NfConfig.CTOR_NAME,
                IsCtor        = true,
                TypeName      = typeName,
                MetadataToken = ci.MetadataToken
            };

            foreach (var parameterInfo in ci.GetParameters())
            {
                var paramType = parameterInfo.NfParameterType();
                var cgArg     = new CgArg
                {
                    ArgName = parameterInfo.Name,
                    ArgType = Settings.LangStyle.TransformClrTypeSyntax(paramType)
                };

                cgMem.Args.Add(cgArg);
            }

            if (!getCallvirtMetadataTokens)
            {
                return(cgMem);
            }

            cgMem.opCodeCallsAndCallvirtsMetadatTokens.AddRange(Asm.GetCallsMetadataTokens(ci));
            return(cgMem);
        }
Example #4
0
        /// <summary>
        /// Test for if <see cref="someMember"/> belongs to this instance.
        /// </summary>
        /// <param name="someMember"></param>
        /// <returns></returns>
        public bool ContainsThisMember(CgMember someMember)
        {
            if (someMember == null)
            {
                return(false);
            }
            if (Properties.Any(p => p.Equals(someMember)))
            {
                return(true);
            }
            if (Fields.Any(f => f.Equals(someMember)))
            {
                return(true);
            }
            if (Events.Any(e => e.Equals(someMember)))
            {
                return(true);
            }
            if (Methods.Any(m => m.Equals(someMember)))
            {
                return(true);
            }

            return(false);
        }
Example #5
0
        /// <summary>
        /// Gets the <see cref="PropertyInfo"/> as a code gen member (<see cref="CgMember"/>)
        /// </summary>
        /// <param name="pi"></param>
        /// <param name="valueTypeOnly"></param>
        /// <param name="enumValueDictionary"></param>
        /// <returns></returns>
        public static CgMember GetAsCgMember(PropertyInfo pi, bool valueTypeOnly,
                                             Dictionary <string, string[]> enumValueDictionary)
        {
            if (pi == null)
            {
                return(null);
            }

            var piType = pi.NfPropertyType();

            if (valueTypeOnly && piType.NfBaseType() != null &&
                piType.NfBaseType().Name != VALUE_TYPE)
            {
                return(null);
            }

            var cgMem = new CgMember
            {
                TypeName         = Settings.LangStyle.TransformClrTypeSyntax(piType),
                IsEnumerableType = NfReflect.IsEnumerableReturnType(piType),
                Name             = pi.Name,
                MetadataToken    = pi.MetadataToken
            };

            if (pi.CanRead)
            {
                cgMem.HasGetter = true;
                if (pi.NfGetGetMethod() != null)
                {
                    cgMem.IsStatic = pi.NfGetGetMethod().IsStatic;
                }
            }

            if (pi.CanWrite)
            {
                cgMem.HasSetter = true;
                if (pi.NfGetSetMethod() != null)
                {
                    cgMem.IsStatic = pi.NfGetSetMethod().IsStatic;
                }
            }

            string[] enumVals;
            if (NfReflect.IsEnumType(piType, out enumVals) && enumValueDictionary != null)
            {
                cgMem.IsEnum = true;
                var clearName = NfReflect.GetLastTypeNameFromArrayAndGeneric(cgMem.TypeName, "<");
                if (!enumValueDictionary.ContainsKey(clearName))
                {
                    enumValueDictionary.Add(clearName, enumVals);
                }
            }

            return(cgMem);
        }
Example #6
0
        /// <summary>
        /// Gets a dictionary for use in replacing content from the original source file.
        /// </summary>
        /// <param name="cgMem"></param>
        /// <param name="newVariableName">Optional, specify the name of the injected instance-level variable.
        /// Default to a random string.</param>
        /// <param name="namespaceAndTypeName">Optional for use in specifying a new namespace and type name.
        /// Defaults to the parent <see cref="CgType"/> values.</param>
        /// <param name="includeVariableDecl">
        /// Specify as true to have the resulting dictionary include where to inject a new
        /// variable declaration.  Typically the very first line after the classes' opening token.
        /// </param>
        /// <returns>
        /// The dictionary's keys are in the form of index, length, same as
        /// in the common <see cref="System.String.Substring(int, int)"/> and represent what is
        /// to be removed from the original source code file while its counterpart values are
        /// what is placed in its stead.
        /// </returns>
        internal static Dictionary <Tuple <int, int>, string[]> MyRefactoredLines(this CgMember cgMem, string newVariableName,
                                                                                  Tuple <string, string> namespaceAndTypeName, bool includeVariableDecl = true)
        {
            if (string.IsNullOrWhiteSpace(cgMem.PdbModuleSymbols?.file) ||
                !File.Exists(cgMem.PdbModuleSymbols.file) ||
                cgMem.PdbModuleSymbols.firstLine == null ||
                cgMem.PdbModuleSymbols.lastLine == null)
            {
                return(null);
            }

            if (string.IsNullOrWhiteSpace(newVariableName))
            {
                newVariableName = Util.Core.NfString.GetNfRandomName();
            }

            int lnNumOut;

            Settings.LangStyle.TryFindFirstLineInClass(cgMem.MyCgType.FullName, File.ReadAllLines(cgMem.PdbModuleSymbols.file),
                                                       out lnNumOut);

            var ofl  = lnNumOut;
            var dido = new Dictionary <Tuple <int, int>, string[]>();

            //allow calling assembly to specify a new namespace and type name
            var renameCgType = namespaceAndTypeName == null
                ? cgMem.MyCgType
                : new CgType()
            {
                Namespace = namespaceAndTypeName.Item1 ?? cgMem.MyCgType.Namespace,
                Name      = namespaceAndTypeName.Item2 ?? cgMem.MyCgType.Name
            };

            //this is an instance level declaration added to the original source
            if (ofl > 1 && includeVariableDecl)
            {
                var oldFilesInstanceToNew = Settings.LangStyle.ToDecl(renameCgType, newVariableName,
                                                                      CgAccessModifier.Private);
                dido.Add(new Tuple <int, int>(ofl, 1), new[] { oldFilesInstanceToNew });
            }

            var minAt = cgMem.PdbModuleSymbols.firstLine.lineNumber;
            var maxAt = cgMem.PdbModuleSymbols.lastLine.lineNumber;

            var nKey = new Tuple <int, int>(minAt,
                                            maxAt - minAt - 1);

            dido.Add(nKey, new[] { Settings.LangStyle.ToStmt(cgMem, null, newVariableName) });
            return(dido);
        }
Example #7
0
        /// <summary>
        /// Gets the <see cref="FieldInfo"/> as a code gen member (<see cref="CgMember"/>)
        /// </summary>
        /// <param name="fi"></param>
        /// <param name="valueTypeOnly"></param>
        /// <param name="enumValueDictionary"></param>
        /// <returns></returns>
        public static CgMember GetAsCgMember(FieldInfo fi, bool valueTypeOnly,
                                             Dictionary <string, string[]> enumValueDictionary)
        {
            if (fi == null)
            {
                return(null);
            }

            if (NfReflect.IsClrGeneratedType(fi.Name))
            {
                return(null);
            }

            var fiType = fi.NfFieldType();

            if (valueTypeOnly && fiType.NfBaseType() != null && fiType.NfBaseType().Name != VALUE_TYPE)
            {
                return(null);
            }

            var cgMem = new CgMember
            {
                TypeName         = Settings.LangStyle.TransformClrTypeSyntax(fiType),
                IsEnumerableType = NfReflect.IsEnumerableReturnType(fiType),
                Name             = fi.Name,
                IsStatic         = fi.IsStatic,
                MetadataToken    = fi.MetadataToken
            };

            string[] enumVals;
            if (NfReflect.IsEnumType(fiType, out enumVals) && enumValueDictionary != null)
            {
                cgMem.IsEnum = true;
                var clearName = NfReflect.GetLastTypeNameFromArrayAndGeneric(cgMem.TypeName, "<");
                if (!enumValueDictionary.ContainsKey(clearName))
                {
                    enumValueDictionary.Add(clearName, enumVals);
                }
            }
            return(cgMem);
        }
Example #8
0
        /// <summary>
        /// Attempts to determine if the ArgNames present herein appear, as
        /// whole words, somewhere in the <see cref="codeBlockLines"/>.
        /// Typically developers will draft signatures where the most important
        /// parameter is furtherest left.  This plays on that by first looking
        /// for all the ArgNames then drops one off the right, tries again and
        /// so forth.
        /// </summary>
        /// <param name="cgMem"></param>
        /// <param name="codeBlockLines"></param>
        /// <returns>
        /// A number being the number of matches for ArgName's found starting
        /// on the left.
        /// </returns>
        /// <remarks>
        /// This logic works if the overloaded signatures are ordered by
        /// the number of parameters having highest go first.
        /// </remarks>
        public static int CodeBlockUsesMyArgs(this CgMember cgMem, string[] codeBlockLines)
        {
            if (cgMem.Args.Count == 0)
            {
                return(0);
            }

            //first get a cleaned up copy of the contents so not mislead by comments
            var cleanCodeBlock = Settings.LangStyle.CleanupPdbLinesCodeBlock(codeBlockLines).ToList();

            //start by looking for all names, failing that, drop one off the right and try again till down to one
            for (var i = cgMem.Args.Count; i > 0; i--)
            {
                var argNameList = cgMem.Args.Take(i).Select(arg => arg.ArgName).ToList();
                var prop        =
                    argNameList.All(arg => cleanCodeBlock.Any(ln => Regex.IsMatch(ln, string.Format(@"\W{0}\W", arg))));
                if (prop)
                {
                    return(i);
                }
            }

            return(0);
        }
Example #9
0
        /// <summary>
        /// Perform binding this <see cref="CgMember"/> to PDB data
        /// </summary>
        /// <param name="cgMem"></param>
        /// <param name="pdbData"></param>
        /// <returns></returns>
        public static bool TryAssignPdbSymbols(this CgMember cgMem, ModuleSymbols[] pdbData)
        {
            if (string.IsNullOrWhiteSpace(cgMem.Name))
            {
                return(false);
            }

            //only expecting multi pdb line files for properties
            if (cgMem.HasGetter || cgMem.HasSetter)
            {
                cgMem.PdbModuleSymbols = new ModuleSymbols();
                if (cgMem.HasGetter)
                {
                    var getterMatch =
                        pdbData.Where(
                            x =>
                            x.symbolName ==
                            string.Format("{0}{1}", NfReflect.PropertyNamePrefix.GET_PREFIX, cgMem.Name))
                        .Select(x => x)
                        .FirstOrDefault();
                    if (getterMatch != null)
                    {
                        cgMem.PdbModuleSymbols = getterMatch;
                    }
                }
                if (cgMem.HasSetter)
                {
                    var setterMatch =
                        pdbData.Where(
                            x =>
                            x.symbolName ==
                            string.Format("{0}{1}", NfReflect.PropertyNamePrefix.SET_PREFIX, cgMem.Name))
                        .Select(x => x)
                        .FirstOrDefault();
                    if (setterMatch != null)
                    {
                        var propMax = setterMatch.lastLine.lineNumber > cgMem.PdbModuleSymbols.lastLine.lineNumber
                            ? setterMatch.lastLine
                            : cgMem.PdbModuleSymbols.lastLine;
                        var propMin = setterMatch.firstLine.lineNumber < cgMem.PdbModuleSymbols.firstLine.lineNumber
                            ? setterMatch.firstLine
                            : cgMem.PdbModuleSymbols.firstLine;

                        cgMem.PdbModuleSymbols           = setterMatch;
                        cgMem.PdbModuleSymbols.firstLine = propMin;
                        cgMem.PdbModuleSymbols.lastLine  = propMax;
                    }
                }
                return(cgMem.PdbModuleSymbols != null);
            }

            //find all the entry keys whose pdbTargetLine's memberName matches this one.
            var matchedPdbTargets = pdbData.Where(x => x.symbolName == cgMem.Name).Select(x => x).ToList();

            if (matchedPdbTargets.Count <= 0)
            {
                return(false);
            }
            if (matchedPdbTargets.Count == 1)
            {
                cgMem.PdbModuleSymbols = matchedPdbTargets.First();
                return(true);
            }

            //thread arriving here means the member is an overloaded function and it gets tricky
            var matchScoreBoard = new Dictionary <ModuleSymbols, int>();

            foreach (var fi in matchedPdbTargets)
            {
                var fiPath = fi.file;

                var idx          = fi.firstLine.lineNumber;
                var len          = fi.lastLine.lineNumber - idx + 1;
                var pdbFileLines = File.ReadAllLines(fiPath).Skip(idx).Take(len).ToArray();
                var matchedScore = CodeBlockUsesMyArgs(cgMem, pdbFileLines);
                matchScoreBoard.Add(fi, matchedScore);
            }

            if (matchScoreBoard.Keys.Count <= 0)
            {
                return(false);
            }
            var bestMatchScore = matchScoreBoard.Max(x => x.Value);

            cgMem.PdbModuleSymbols = matchScoreBoard.First(x => x.Value == bestMatchScore).Key;

            return(true);
        }
Example #10
0
        /// <summary>
        /// Useful for refactoring, finds a list of all instance level fields, properties
        /// and methods which are used within this member's implementation.
        /// </summary>
        /// <param name="cgMem"></param>
        /// <returns> </returns>
        /// <remarks>
        /// Depends on PDB data, results are not derived from assembly reflection.
        /// </remarks>
        public static List <CgArg> GetAllRefactorDependencies(this CgMember cgMem)
        {
            if (cgMem.PdbModuleSymbols == null || string.IsNullOrWhiteSpace(cgMem.PdbModuleSymbols.file) ||
                !File.Exists(cgMem.PdbModuleSymbols.file))
            {
                return(null);
            }

            var idx = cgMem.PdbModuleSymbols.firstLine.lineNumber;
            var len = cgMem.PdbModuleSymbols.lastLine.lineNumber - idx + 1;

            var ssrcCode =
                File.ReadAllLines(cgMem.PdbModuleSymbols.file)
                .Skip(idx)
                .Take(len)
                .ToArray();

            if (ssrcCode.Length <= 0)
            {
                return(null);
            }

            var dependencyArgs = new List <CgArg>();

            var  flattenCode = new string(Settings.LangStyle.FlattenCodeToCharStream(ssrcCode).ToArray());
            bool irregular   = false;

            flattenCode = Settings.LangStyle.EscStringLiterals(flattenCode, EscapeStringType.UNICODE, ref irregular);

            var instanceMembers =
                cgMem.MyCgType.Fields.Where(f => Regex.IsMatch(flattenCode, f.AsInvokeRegexPattern())).ToList();

            //apply filters since arg names and types may be duplicated with instance variables.
            dependencyArgs.AddRange(
                instanceMembers.Select(ic => Settings.LangStyle.ToParam(ic, false))
                .Where(x => cgMem.Args.All(myArg => !myArg.Equals(x) && dependencyArgs.All(nArg => !nArg.Equals(x)))));

            instanceMembers =
                cgMem.MyCgType.Properties.Where(p => Regex.IsMatch(flattenCode, p.AsInvokeRegexPattern())).ToList();
            dependencyArgs.AddRange(
                instanceMembers.Select(ic => Settings.LangStyle.ToParam(ic, false))
                .Where(x => cgMem.Args.All(myArg => !myArg.Equals(x) && dependencyArgs.All(nArg => !nArg.Equals(x)))));

            instanceMembers =
                cgMem.MyCgType.Methods.Where(
                    m => Regex.IsMatch(flattenCode, m.AsInvokeRegexPattern())).ToList();
            dependencyArgs.AddRange(
                instanceMembers.Select(ic => Settings.LangStyle.ToParam(ic, true))
                .Where(x => cgMem.Args.All(myArg => !myArg.Equals(x) && dependencyArgs.All(nArg => !nArg.Equals(x)))));

            //arg names common to obj methods will cause confusion
            var objMethods = typeof(object).GetMethods().Select(x => x.Name).ToArray();

            foreach (var dpArg in dependencyArgs)
            {
                if (objMethods.Contains(dpArg.ArgName))
                {
                    dpArg.ArgName = string.Format("{0}{1}", Util.Core.NfString.DefaultNamePrefix, dpArg.ArgName);
                }
            }

            return(dependencyArgs);
        }
Example #11
0
        /// <summary>
        /// Gets a method as a code gen member type
        /// </summary>
        /// <param name="mti"></param>
        /// <param name="getCallvirtMetadataTokens"></param>
        /// <returns></returns>
        public static CgMember GetAsCgMember(MethodInfo mti, bool getCallvirtMetadataTokens = false)
        {
            if (mti == null)
            {
                return(null);
            }
            if (NfReflect.IsClrMethodForProperty(mti.Name, out _))
            {
                return(null);
            }
            if (NfReflect.IsClrGeneratedType(mti.Name))
            {
                //these appear as '<SomeNameOfMethodAlreadyAdded>b__kifkj(...)'
                return(null);
            }

            var miReturnType = mti.NfReturnType();

            var cgMem = new CgMember
            {
                Name             = mti.Name,
                TypeName         = Settings.LangStyle.TransformClrTypeSyntax(miReturnType),
                IsStatic         = mti.IsStatic,
                IsGeneric        = mti.IsGenericMethod,
                IsEnumerableType = NfReflect.IsEnumerableReturnType(miReturnType),
                IsMethod         = true,
                MetadataToken    = mti.MetadataToken
            };

            if (mti.IsAssembly)
            {
                cgMem.AccessModifier = CgAccessModifier.Assembly;
            }
            if (mti.IsFamily)
            {
                cgMem.AccessModifier = CgAccessModifier.Family;
            }
            if (mti.IsFamilyAndAssembly)
            {
                cgMem.AccessModifier = CgAccessModifier.FamilyAssembly;
            }
            if (mti.IsPrivate)
            {
                cgMem.AccessModifier = CgAccessModifier.Private;
            }
            if (mti.IsPublic)
            {
                cgMem.AccessModifier = CgAccessModifier.Public;
            }

            foreach (var parameterInfo in mti.GetParameters())
            {
                var paramType = parameterInfo.NfParameterType();
                var cgArg     = new CgArg
                {
                    ArgName = parameterInfo.Name,
                    ArgType = Settings.LangStyle.TransformClrTypeSyntax(paramType)
                };

                cgMem.Args.Add(cgArg);
            }
            cgMem.MethodBodyIL = Convert.ToBase64String(Asm.GetMethodBody(mti));

            if (!getCallvirtMetadataTokens)
            {
                return(cgMem);
            }

            cgMem.opCodeCallsAndCallvirtsMetadatTokens.AddRange(Asm.GetCallsMetadataTokens(mti));
            return(cgMem);
        }
Example #12
0
        /// <summary>
        /// Resolves all MetadataTokens present in <see cref="cgm"/> using the <see cref="manifestModule"/>
        /// </summary>
        /// <param name="cgm"></param>
        /// <param name="manifestModule"></param>
        /// <param name="memberInfoCache">
        /// Optional cache dictionary for use when this is being called within a loop, helps performance.
        /// </param>
        /// <param name="ignoreAssemblyFullNames">
        /// Optional list of fully-qualified assembly names whose members should NOT be added (e.g. mscorlib).
        /// </param>
        /// <param name="maxErrors">The max number of exceptions to be incurred before abandoning.</param>
        /// <returns>Count of errors encountered, will range from 0 to <see cref="maxErrors"/></returns>
        public static int ResolveCgMemberMetadataTokens(CgMember cgm, Module manifestModule,
                                                        Dictionary <int, MemberInfo> memberInfoCache, string[] ignoreAssemblyFullNames, int maxErrors = 5)
        {
            if (cgm == null)
            {
                return(maxErrors);
            }
            if (manifestModule == null)
            {
                return(maxErrors);
            }

            var errorCount = 0;

            //for each method, get all invoked metadata tokens
            foreach (var metadataToken in cgm.opCodeCallsAndCallvirtsMetadatTokens)
            {
                try
                {
                    MemberInfo runtimeMem = null;
                    //resolve invoked metadata token to a member type
                    if (memberInfoCache != null && memberInfoCache.ContainsKey(metadataToken))
                    {
                        runtimeMem = memberInfoCache[metadataToken];
                    }
                    else
                    {
                        runtimeMem = manifestModule.ResolveMember(metadataToken);
                    }
                    if (runtimeMem == null)
                    {
                        continue;
                    }
                    var declaringType        = runtimeMem.DeclaringType;
                    var declaringTypeAsmName = declaringType?.AssemblyQualifiedName;

                    if (string.IsNullOrWhiteSpace(declaringTypeAsmName))
                    {
                        continue;
                    }

                    if (ignoreAssemblyFullNames != null && ignoreAssemblyFullNames.Any(declaringTypeAsmName.EndsWith))
                    {
                        continue;
                    }

                    //add to cache for performance
                    if (memberInfoCache != null && !memberInfoCache.ContainsKey(metadataToken))
                    {
                        memberInfoCache.Add(metadataToken, runtimeMem);
                    }

                    var runtimeMi = runtimeMem as MethodInfo;
                    if (runtimeMi != null)
                    {
                        var ncgm = GetAsCgMember(runtimeMi, false);
                        if (ncgm == null)
                        {
                            continue;
                        }
                        ncgm.MetadataToken        = metadataToken;
                        ncgm.DeclaringTypeAsmName = declaringTypeAsmName;

                        cgm.OpCodeCallAndCallvirts.Add(ncgm);
                        continue;
                    }

                    var runtimePi = runtimeMem as PropertyInfo;
                    if (runtimePi != null)
                    {
                        var ncgm = GetAsCgMember(runtimePi, false, null);
                        if (ncgm == null)
                        {
                            continue;
                        }

                        ncgm.MetadataToken        = metadataToken;
                        ncgm.DeclaringTypeAsmName = declaringTypeAsmName;
                        cgm.OpCodeCallAndCallvirts.Add(ncgm);
                        continue;
                    }

                    var runtimeFi = runtimeMem as FieldInfo;
                    if (runtimeFi == null)
                    {
                        continue;
                    }

                    var fiCgm = GetAsCgMember(runtimeFi, false, null);
                    if (fiCgm == null)
                    {
                        continue;
                    }
                    fiCgm.MetadataToken        = metadataToken;
                    fiCgm.DeclaringTypeAsmName = declaringTypeAsmName;
                    cgm.OpCodeCallAndCallvirts.Add(fiCgm);
                }
                catch
                {
                    errorCount += 1;
                    if (errorCount > maxErrors)
                    {
                        break;
                    }
                }
            }
            return(errorCount);
        }
Example #13
0
        /// <summary>
        /// Converts the .NET type into the custom Code Gen type
        /// </summary>
        /// <param name="asmType"></param>
        /// <param name="valueTypeOnly">
        /// Will only export Fields and Properties whose base type extends System.ValueType
        /// </param>
        /// <param name="resolveDependencies">
        /// Switch to have the IL of the type parsed and all dependent calls Metadata tokens added.
        /// </param>
        /// <returns></returns>
        public static CgType GetCgOfType(this Type asmType, bool valueTypeOnly, bool resolveDependencies = false)
        {
            var cgType = new CgType();

            if (asmType == null || NfReflect.IsIgnoreType(asmType) || NfReflect.IsClrGeneratedType(asmType))
            {
                return(null);
            }

            //use the logic in TypeName to get the namespace and class name so its not tied to having the assembly
            var cgTypeName = new NfTypeName(asmType.AssemblyQualifiedName);

            //make sure there is always some kind of namespace
            cgType.Namespace = string.IsNullOrWhiteSpace(cgTypeName.Namespace)
                ? asmType.Assembly.GetName().Name
                : cgTypeName.Namespace;
            cgType.IsContrivedNamespace = string.IsNullOrWhiteSpace(cgTypeName.Namespace);
            cgType.Name = cgTypeName.ClassName;
            cgType.AssemblyQualifiedName = asmType.AssemblyQualifiedName;
            cgType.IsEnum = NfReflect.IsEnumType(asmType);

            var cgTypesInterfaces = asmType.GetInterfaces();

            cgType.MetadataToken = asmType.MetadataToken;

            Func <CgType, string, bool> alreadyPresentHerein =
                (cg, nextName) =>
                (cg.Properties.FirstOrDefault(
                     cgP => string.Equals(cgP.Name, nextName, StringComparison.OrdinalIgnoreCase)) != null
                 ||
                 cg.Fields.FirstOrDefault(
                     cgF => string.Equals(cgF.Name, nextName, StringComparison.OrdinalIgnoreCase)) != null
                 ||
                 cg.Events.FirstOrDefault(
                     cgE => string.Equals(cgE.Name, nextName, StringComparison.OrdinalIgnoreCase)) != null)
            ;

            //have events go first since they tend to be speard across fields and properties
            foreach (
                var evtInfo in
                asmType.GetEvents(Shared.Core.NfSettings.DefaultFlags))
            {
                var evtHandlerType = evtInfo.NfEventHandlerType().ToString();

                var cgMem = new CgMember
                {
                    Name          = evtInfo.Name,
                    TypeName      = evtHandlerType,
                    MetadataToken = evtInfo.MetadataToken
                };
                cgType.Events.Add(cgMem);
            }

            var asmMembers =
                asmType.GetMembers(Shared.Core.NfSettings.DefaultFlags);

            foreach (var mi in asmMembers)
            {
                if (alreadyPresentHerein(cgType, mi.Name))
                {
                    continue;
                }

                try
                {
                    if (mi.MemberType == MemberTypes.Property)
                    {
                        var pi = mi as PropertyInfo;

                        var cgm = GetAsCgMember(pi, valueTypeOnly, cgType.EnumValueDictionary);
                        if (cgm == null)
                        {
                            continue;
                        }
                        if (resolveDependencies)
                        {
                            var propMi = NfReflect.GetMethodsForProperty(pi, asmType);
                            foreach (var pim in propMi)
                            {
                                cgm.opCodeCallsAndCallvirtsMetadatTokens.AddRange(Asm.GetCallsMetadataTokens(pim));
                            }
                        }
                        cgType.Properties.Add(cgm);
                    }
                }
                catch (Exception ex)
                {
                    Asm.AddLoaderExceptionToLog(null, ex);

                    if (!Settings.IgnoreReflectionMissingAsmError)
                    {
                        throw;
                    }

                    cgType.Properties.Add(new CgMember
                    {
                        Name      = mi.Name,
                        TypeName  = DF_TYPE_NAME,
                        HasGetter = true,
                        HasSetter = true,
                        SkipIt    = true
                    });
                }

                try
                {
                    if (mi.MemberType == MemberTypes.Event)
                    {
                        continue;//these have already been handled
                    }
                }
                catch (Exception ex)
                {
                    Asm.AddLoaderExceptionToLog(null, ex);
                    continue;
                }

                try
                {
                    if (mi.MemberType == MemberTypes.Field)
                    {
                        var fi  = mi as FieldInfo;
                        var cgm = GetAsCgMember(fi, valueTypeOnly, cgType.EnumValueDictionary);

                        if (cgm == null)
                        {
                            continue;
                        }
                        cgType.Fields.Add(cgm);
                    }
                }
                catch (Exception ex)
                {
                    Asm.AddLoaderExceptionToLog(null, ex);
                    if (!Settings.IgnoreReflectionMissingAsmError)
                    {
                        throw;
                    }

                    cgType.Fields.Add(new CgMember
                    {
                        Name     = mi.Name,
                        TypeName = DF_TYPE_NAME,
                        SkipIt   = true
                    });
                }
                try
                {
                    if (!valueTypeOnly && mi.MemberType == MemberTypes.Method)
                    {
                        var mti = mi as MethodInfo;
                        var cgm = GetAsCgMember(mti, resolveDependencies);

                        if (cgm == null)
                        {
                            continue;
                        }
                        cgm.IsInterfaceImpl = IsInterfaceImpl(mti, cgTypesInterfaces);
                        cgType.Methods.Add(cgm);
                    }

                    if (!valueTypeOnly && mi.MemberType == MemberTypes.Constructor)
                    {
                        var ci = mi as ConstructorInfo;
                        var tn = (string.IsNullOrWhiteSpace(cgTypeName.Namespace)
                            ? cgTypeName.ClassName
                            : $"{cgTypeName.Namespace}.{cgTypeName.ClassName}");

                        var cgm = GetAsCgMember(ci, tn, resolveDependencies);

                        if (cgm == null)
                        {
                            continue;
                        }
                        cgType.Methods.Add(cgm);
                    }
                }
                catch (Exception ex)
                {
                    Asm.AddLoaderExceptionToLog(null, ex);
                    if (!Settings.IgnoreReflectionMissingAsmError)
                    {
                        throw;
                    }

                    cgType.Methods.Add(new CgMember
                    {
                        Name     = mi.Name,
                        TypeName = DF_TYPE_NAME,
                        SkipIt   = true
                    });
                }
            }

            if (resolveDependencies)
            {
                ResolveAllMetadataTokens(cgType, asmType.Assembly.ManifestModule);
            }

            return(cgType);
        }