Esempio n. 1
0
        private static void AddSampleTypes(MutableSymbol packageRoot, string frameworkTargets, bool addMemoryType)
        {
            string fx = frameworkTargets.ToFrameworkNames().First();

            MutableSymbol assembly        = packageRoot.AddChild(new MutableSymbol(DLL_NAME, SymbolType.Assembly));
            MutableSymbol frameworkTarget = assembly.AddChild(new MutableSymbol(frameworkTargets, SymbolType.FrameworkTarget));
            MutableSymbol sample          = frameworkTarget.AddChild(new MutableSymbol(NS_SAMPLE, SymbolType.Namespace));
            MutableSymbol diagnostics     = sample.AddChild(new MutableSymbol(NS_DIAGNOSTICS, SymbolType.Namespace));
            MutableSymbol logger          = diagnostics.AddChild(new MutableSymbol(TYPE_LOGGER, SymbolType.Class)
            {
                Modifiers = SymbolModifier.Public, FilePath = @"src\" + fx + @"\Diagnostics\Logger.cs", Line = 8, CharInLine = 18
            });

            logger.AddChild(new MutableSymbol(TYPE_LOGGER, SymbolType.Constructor)
            {
                Modifiers = SymbolModifier.Public, Parameters = "string", FilePath = @"src\" + fx + @"\Diagnostics\Logger.cs", Line = 22, CharInLine = 16
            });
            logger.AddChild(new MutableSymbol("LogUse", SymbolType.Method)
            {
                Modifiers = SymbolModifier.Public, FilePath = @"src\" + fx + @"\Diagnostics\Logger.cs", Line = 32, CharInLine = 21
            });
            logger.AddChild(new MutableSymbol("LogException", SymbolType.Method)
            {
                Modifiers = SymbolModifier.Public, Parameters = "Exception", FilePath = @"src\" + fx + @"\Diagnostics\Logger.cs", Line = 37, CharInLine = 21
            });
            logger.AddChild(new MutableSymbol("TryLog", SymbolType.Method)
            {
                Modifiers = SymbolModifier.Private, Parameters = "string, string", FilePath = @"src\" + fx + @"\Diagnostics\Logger.cs", Line = 44, CharInLine = 22
            });

            // Nested public types should appear in the IDX but not the ARDB
            logger.AddChild(new MutableSymbol("NestedPublicType", SymbolType.Class)
            {
                Modifiers = SymbolModifier.Public, FilePath = @"src\" + fx + @"\Diagnostics\Logger.cs", Line = 22, CharInLine = 16
            });

            if (addMemoryType)
            {
                MutableSymbol memory = diagnostics.AddChild(new MutableSymbol(TYPE_MEMORY, SymbolType.Class)
                {
                    Modifiers = SymbolModifier.Public | SymbolModifier.Static, FilePath = @"src\" + fx + @"\Diagnostics\Memory.cs", Line = 5, CharInLine = 25
                });
                memory.AddChild(new MutableSymbol("MeasureObjectSize", SymbolType.Method)
                {
                    Modifiers = SymbolModifier.Public | SymbolModifier.Static, Parameters = "Func<object>", FilePath = @"src\" + fx + @"\Diagnostics\Memory.cs", Line = 13, CharInLine = 28
                });
                memory.AddChild(new MutableSymbol("FromGigabytes", SymbolType.Method)
                {
                    Modifiers = SymbolModifier.Public | SymbolModifier.Static, Parameters = "double", FilePath = @"src\" + fx + @"\Diagnostics\Memory.cs", Line = 32, CharInLine = 28
                });
            }
        }
Esempio n. 2
0
        private void WalkMethod(MetadataReader mdReader, MethodDefinitionHandle handle, MutableSymbol parent)
        {
            MethodDefinition method     = mdReader.GetMethodDefinition(handle);
            MethodAttributes attributes = method.Attributes;
            string           name       = mdReader.GetString(method.Name);

            MutableSymbol result = new MutableSymbol(name, GetMethodType(attributes, name));

            AddModifiers(attributes, result);
            AddLocation(handle, result);
            AddParameters(mdReader, method, result);

            // Make Constructor/Destructors use the type name as the method name [like Ctrl+, search]
            if (result.Type == SymbolType.Constructor || result.Type == SymbolType.StaticConstructor || result.Type == SymbolType.Destructor)
            {
                result.Name = parent.Name.ToString();
            }

            if (IsExcluded(result))
            {
                return;
            }

            parent.AddChild(result);

            // TODO: Identify Extension Methods. Issue: Requires a lot of Blob reading. See http://source.roslyn.io/#q=PEMethodSymbol.IsExtensionMethod, http://source.roslyn.io/#q=PEModule.HasExtensionAttribute
        }
Esempio n. 3
0
        private void WalkMethod(IMethodSymbol method, MutableSymbol parent)
        {
            MutableSymbol result = new MutableSymbol(method.AdjustedName(), GetMethodType(method));

            AddModifiers(method, result);
            AddLocation(method, result);

            if (this.IncludeSignatures)
            {
                result.Parameters = method.MinimalParameters();
            }

            if (IsExcluded(method, result))
            {
                return;
            }

            parent.AddChild(result);

            // Add the extended type under Extension Methods
            if (result.Type == SymbolType.ExtensionMethod && method.Parameters.Length > 0)
            {
                IParameterSymbol thisParameter = method.Parameters[0];
                ITypeSymbol      thisType      = thisParameter.Type;
                MutableSymbol    extendedType  = new MutableSymbol(thisType.NamespaceAndName(), SymbolType.ExtendedType);
                extendedType.Modifiers = result.Modifiers;
                result.AddChild(extendedType);
            }
        }
Esempio n. 4
0
        private void WalkProject(Project project, MutableSymbol parent)
        {
            // Get the consolidated assembly symbols and walk them
            Compilation     rootCompilation = project.GetCompilationAsync().Result;
            IAssemblySymbol assembly        = rootCompilation.Assembly;

            MutableSymbol assemblyRoot = parent.AddChild(new MutableSymbol(Path.GetFileName(project.OutputFilePath), SymbolType.Assembly));

            WalkNamespace(assembly.GlobalNamespace, assemblyRoot);
        }
Esempio n. 5
0
        private void WalkField(IFieldSymbol field, MutableSymbol parent)
        {
            MutableSymbol result = new MutableSymbol(field.Name, GetFieldType(field));

            AddModifiers(field, result);
            AddLocation(field, result);

            if (!IsExcluded(field, result))
            {
                parent.AddChild(result);
            }
        }
Esempio n. 6
0
        private void WalkField(MetadataReader mdReader, FieldDefinitionHandle handle, MutableSymbol parent)
        {
            FieldDefinition field = mdReader.GetFieldDefinition(handle);

            MutableSymbol result = new MutableSymbol(mdReader.GetString(field.Name), SymbolType.Field);

            AddModifiers(field.Attributes, result);
            AddLocation(handle, result);

            if (IsExcluded(result))
            {
                return;
            }
            parent.AddChild(result);
        }
Esempio n. 7
0
        private void WalkType(INamedTypeSymbol symbol, MutableSymbol parent)
        {
            // Build this type
            MutableSymbol result = new MutableSymbol(symbol.Name, GetNamedTypeType(symbol));

            AddModifiers(symbol, result);
            AddLocation(symbol, result);

            // Stop if it should be excluded
            if (IsExcluded(symbol, result))
            {
                return;
            }

            // Add the type itself
            MutableSymbol thisSymbol = parent.AddChild(result);

            // Recurse on members
            foreach (ISymbol child in symbol.GetMembers())
            {
                if (child is INamedTypeSymbol)
                {
                    WalkType((INamedTypeSymbol)child, thisSymbol);
                }
                else
                {
                    if (this.IncludeMembers)
                    {
                        if (child is IMethodSymbol)
                        {
                            WalkMethod((IMethodSymbol)child, thisSymbol);
                        }
                        else if (child is IPropertySymbol)
                        {
                            WalkProperty((IPropertySymbol)child, thisSymbol);
                        }
                        else if (child is IFieldSymbol)
                        {
                            WalkField((IFieldSymbol)child, thisSymbol);
                        }
                        else
                        {
                            // Other contents excluded
                        }
                    }
                }
            }
        }
Esempio n. 8
0
        private void WalkType(MetadataReader mdReader, TypeDefinitionHandle handle, MutableSymbol parent)
        {
            TypeDefinition type       = mdReader.GetTypeDefinition(handle);
            var            attributes = type.Attributes;

            // Get the name and remove generic suffix (List`1 => List)
            string metadataName           = mdReader.GetString(type.Name);
            int    genericNameSuffixIndex = metadataName.IndexOf('`');
            string baseName = (genericNameSuffixIndex < 0 ? metadataName : metadataName.Substring(0, genericNameSuffixIndex));

            MutableSymbol result = new MutableSymbol(baseName, GetTypeType(mdReader, type));

            AddModifiers(attributes, result);
            AddLocation(handle, result);

            if (IsExcluded(result))
            {
                return;
            }
            parent.AddChild(result);

            foreach (TypeDefinitionHandle nestedTypeHandle in type.GetNestedTypes())
            {
                WalkType(mdReader, nestedTypeHandle, result);
            }

            if (this.IncludeMembers)
            {
                foreach (MethodDefinitionHandle methodHandle in type.GetMethods())
                {
                    WalkMethod(mdReader, methodHandle, result);
                }

                foreach (FieldDefinitionHandle fieldHandle in type.GetFields())
                {
                    WalkField(mdReader, fieldHandle, result);
                }

                foreach (PropertyDefinitionHandle propertyHandle in type.GetProperties())
                {
                    WalkProperty(mdReader, propertyHandle, result);
                }

                // NOTE: type.GetEvents, type.GetInterfaceImplementations are not converted.
            }
        }
Esempio n. 9
0
        private void WalkProperty(IPropertySymbol property, MutableSymbol parent)
        {
            MutableSymbol result = new MutableSymbol(property.Name, GetPropertyType(property));

            AddModifiers(property, result);
            AddLocation(property, result);

            if (this.IncludeSignatures)
            {
                result.Parameters = property.MinimalParameters();
            }

            if (!IsExcluded(property, result))
            {
                parent.AddChild(result);
            }
        }
Esempio n. 10
0
        public void Walk(string binaryPath, MutableSymbol parent)
        {
            if (!FileIO.IsManagedBinary(binaryPath))
            {
                throw new ArgumentException(String.Format("SrmCrawler doesn't know how to walk file with extension '{0}'", Path.GetExtension(binaryPath)));
            }

            FileStream stream = new FileStream(binaryPath, FileMode.Open, FileAccess.Read);

            // NOTE: Need to keep PEReader alive through crawl to avoid AV in looking up signatures
            using (PEReader peReader = new PEReader(stream))
            {
                if (peReader.HasMetadata == false)
                {
                    return;
                }

                Trace.WriteLine("\t" + binaryPath);

                using (PdbSymbolProvider pdbProvider = PdbSymbolProvider.TryBuildProvider(binaryPath))
                {
                    PDB = pdbProvider;

                    MutableSymbol assemblyRoot = parent.AddChild(new MutableSymbol(Path.GetFileName(binaryPath), SymbolType.Assembly));

                    // Walk all non-nested types. Namespaces are derived as found. Nested types will be found during crawl of containing type.
                    MetadataReader mdReader = peReader.GetMetadataReader();
                    foreach (TypeDefinitionHandle typeHandle in mdReader.TypeDefinitions)
                    {
                        TypeDefinition type            = mdReader.GetTypeDefinition(typeHandle);
                        string         namespaceString = mdReader.GetString(type.Namespace);

                        if (!type.Attributes.IsNested())
                        {
                            MutableSymbol ns = assemblyRoot.FindOrAddPath(namespaceString, '.', SymbolType.Namespace);
                            WalkType(mdReader, typeHandle, ns);
                        }
                    }
                }
            }
        }
Esempio n. 11
0
        private void WalkProperty(MetadataReader mdReader, PropertyDefinitionHandle handle, MutableSymbol parent)
        {
            PropertyDefinition prop = mdReader.GetPropertyDefinition(handle);

            MutableSymbol result = new MutableSymbol(mdReader.GetString(prop.Name), SymbolType.Property);

            // Use the accessibility and location of the getter [or setter, if write only property]
            // Not identical to Roslyn PEPropertyDeclaration but much simpler
            MethodDefinitionHandle getterOrSetterHandle = prop.GetAccessors().Getter;

            if (getterOrSetterHandle.IsNil)
            {
                getterOrSetterHandle = prop.GetAccessors().Setter;
            }

            // If we couldn't retrieve a getter or setter, exclude this property
            if (getterOrSetterHandle.IsNil)
            {
                return;
            }

            MethodDefinition getterOrSetter = mdReader.GetMethodDefinition(getterOrSetterHandle);

            AddModifiers(getterOrSetter.Attributes, result);
            AddLocation(getterOrSetterHandle, result);
            AddParameters(mdReader, getterOrSetter, result);

            // If this is an Indexer, rename it and retype it
            // Roslyn PEPropertySymbol.IsIndexer is also just based on the name.
            if (result.Name == "Item")
            {
                result.Name = "this[]";
                result.Type = SymbolType.Indexer;
            }

            if (IsExcluded(result))
            {
                return;
            }
            parent.AddChild(result);
        }
Esempio n. 12
0
        private void WalkNamespace(INamespaceSymbol ns, MutableSymbol parent)
        {
            // Build a MutableSymbol for this namespace; collapse the global namespace right under the binary
            MutableSymbol thisSymbol = parent;

            if (!ns.IsGlobalNamespace)
            {
                thisSymbol = parent.AddChild(new MutableSymbol(ns.Name, SymbolType.Namespace));
            }

            // Enumerate child namespaces
            foreach (INamespaceSymbol childNamespace in ns.GetNamespaceMembers())
            {
                WalkNamespace(childNamespace, thisSymbol);
            }

            // Enumerate types
            foreach (INamedTypeSymbol childType in ns.GetTypeMembers())
            {
                WalkType(childType, thisSymbol);
            }
        }
Esempio n. 13
0
        public void MergedMembersDatabase_Merging()
        {
            MergedMembersDatabase db = new MergedMembersDatabase();
            DatabaseAddResult     result;
            string lastAddResult;

            PackageDatabase source = PackageDatabaseTests.BuildDefaultSample();

            source.Identity.PackageName = "V1";
            result        = db.Add(source, ArdbVersion.Current);
            lastAddResult = Write.ToString(result.WriteMemberResults);
            Trace.WriteLine("First Sample Import:\r\n" + lastAddResult);
            Trace.WriteLine(Write.ToString(result.WriteDuplicateComponents));

            // Sample has at least one unique thing
            Assert.IsTrue(result.WasMemberAdded[0].Value);

            // Memory class is included
            Assert.IsTrue(result.WasMemberAdded[ItemTreeTests.FindByPath(source.DeclaredMembers, source.StringStore, DIAGNOSTICS_NAMESPACE_REF35 + "|Memory", PackageDatabaseTests.SEPARATOR_CHAR)].Value);

            // FromGigabytes member is ignored (not a type)
            Assert.IsFalse(result.WasMemberAdded[ItemTreeTests.FindByPath(source.DeclaredMembers, source.StringStore, DIAGNOSTICS_NAMESPACE_REF35 + "|Memory|FromGigabytes", PackageDatabaseTests.SEPARATOR_CHAR)].HasValue);

            // Add the source again (a complete duplicate)
            source.Identity.PackageName = "V2";
            result        = db.Add(source, ArdbVersion.Current);
            lastAddResult = Write.ToString(result.WriteMemberResults);
            Trace.WriteLine("Duplicate Sample Import:\r\n" + lastAddResult);
            Trace.WriteLine(Write.ToString(result.WriteDuplicateComponents));

            // Verify nothing is unique this time
            Assert.IsFalse(result.WasMemberAdded[0].Value);

            // Add a new public class to the sample (should be added)
            MutableSymbol diagnostics = source.MutableRoot.FindByFullName(DIAGNOSTICS_NAMESPACE_LIB20, PackageDatabaseTests.SEPARATOR_CHAR);

            diagnostics.AddChild(new MutableSymbol("TraceWatch", SymbolType.Class)
            {
                Modifiers = SymbolModifier.Public | SymbolModifier.Static
            });

            // Add a new method to Logger (no effect)
            MutableSymbol logger = source.MutableRoot.FindByFullName(DIAGNOSTICS_NAMESPACE_LIB20 + "|Logger", PackageDatabaseTests.SEPARATOR_CHAR);

            logger.AddChild(new MutableSymbol("LogTime", SymbolType.Method)
            {
                Modifiers = SymbolModifier.Public
            });

            // Add the source with additions, verify something is new
            source.Identity.PackageName = "V3";
            result        = db.Add(source, ArdbVersion.Current);
            lastAddResult = Write.ToString(result.WriteMemberResults);
            Trace.WriteLine("Sample with additions Import:\r\n" + lastAddResult);
            Trace.WriteLine(Write.ToString(result.WriteDuplicateComponents));
            Assert.IsTrue(result.WasMemberAdded[0].Value);

            // Verify Diagnostics contains changes
            Assert.IsTrue(result.WasMemberAdded[ItemTreeTests.FindByPath(source.DeclaredMembers, source.StringStore, DIAGNOSTICS_NAMESPACE_LIB20, PackageDatabaseTests.SEPARATOR_CHAR)].Value);

            // Verify Logger wasn't considered changed
            Assert.IsFalse(result.WasMemberAdded[ItemTreeTests.FindByPath(source.DeclaredMembers, source.StringStore, TYPE_LOGGER, PackageDatabaseTests.SEPARATOR_CHAR)].Value);

            // Add a new private class to the sample (should not be added)
            diagnostics.AddChild(new MutableSymbol("SmartTimer", SymbolType.Class)
            {
                Modifiers = SymbolModifier.Internal
            });

            // Add the source again, verify nothing is new
            source.Identity.PackageName = "V4";
            result        = db.Add(source, ArdbVersion.Current);
            lastAddResult = Write.ToString(result.WriteMemberResults);
            Trace.WriteLine("Sample with private class Import:\r\n" + lastAddResult);
            Trace.WriteLine(Write.ToString(result.WriteDuplicateComponents));
            Assert.IsFalse(result.WasMemberAdded[0].Value);

            Trace.WriteLine(Write.ToString((w) => db.WriteMergedTree(w)));
        }
Esempio n. 14
0
        private void WalkBinary(string binaryPath, MutableSymbol parent, string encodedFrameworkNames)
        {
            // Add the binary as a reference to resolve symbols in it
            MetadataReference reference = MetadataReference.CreateFromFile(binaryPath);

            CSharpCompilationOptions compilationOptions = new CSharpCompilationOptions(
                outputKind: OutputKind.ConsoleApplication,
                reportSuppressedDiagnostics: false);

            compilationOptions.SetMetadataImportOptions(MetadataImportOptions.All);

            // Create an empty binary to 'host' the reference
            CSharpCompilation emptyCompilation = CSharpCompilation.Create("Empty.exe", references: new[] { reference }, options: compilationOptions);

            // Get the root of the reference specifically
            ISymbol referenceRootSymbol = emptyCompilation.GetAssemblyOrModuleSymbol(reference);

            // If this wasn't a managed assembly, don't add anything
            if (referenceRootSymbol == null)
            {
                return;
            }

            string           assemblyName    = null;
            INamespaceSymbol globalNamespace = null;

            if (referenceRootSymbol is IAssemblySymbol)
            {
                // NOTE: Use the Assembly.Identity.Name specifically as the root to allow VS to identify binaries (potentially) already referenced safely.
                assemblyName    = ((IAssemblySymbol)referenceRootSymbol).Identity.Name;
                globalNamespace = ((IAssemblySymbol)referenceRootSymbol).GlobalNamespace;
            }
            else if (referenceRootSymbol is IModuleSymbol)
            {
                assemblyName    = Path.GetFileName(binaryPath);
                globalNamespace = ((IModuleSymbol)referenceRootSymbol).GlobalNamespace;
            }
            else
            {
                // Unable to crawl if we didn't find an assembly or module
                Trace.WriteLine(String.Format("ERROR: Unable to crawl binary with root symbol type '{0}'", referenceRootSymbol.GetType().Name));
                return;
            }

            // Walk the binary
            MutableSymbol addUnderRoot = parent.AddChild(new MutableSymbol(assemblyName, SymbolType.Assembly));

            // Add the target framework [if requested and identifiable]
            if (this.IncludeFrameworkTargets)
            {
                if (!String.IsNullOrEmpty(encodedFrameworkNames))
                {
                    addUnderRoot = addUnderRoot.AddChild(new MutableSymbol(encodedFrameworkNames, SymbolType.FrameworkTarget));
                }
            }

            // PRIVATE ROSLYN: Attempt to build a PDB reader for the binary
            using (PdbSymbolProvider pdbProvider = PdbSymbolProvider.TryBuildProvider(binaryPath))
            {
                PDB = pdbProvider;

                WalkNamespace(globalNamespace, addUnderRoot);

                // Remove the PdbSymbolProvider
                PDB = null;
            }
        }
Esempio n. 15
0
        private void AddReferenceDatabaseBasicHelper(ArdbVersion version)
        {
            AddReferenceDatabase ardb = new AddReferenceDatabase(version);
            DatabaseAddResult    result;

            // Build and add the sample PackageDatabase
            PackageDatabase source = PackageDatabaseTests.BuildDefaultSample("V1");

            result = CallAddUniqueMembers(ardb, source);

            // Verify at least something was added
            int ardbCountFirstAdd = ardb.Count;

            Assert.IsTrue(result.WasMemberAdded[0].Value);

            // Add the sample again; verify nothing was added
            source = PackageDatabaseTests.BuildDefaultSample("V2");
            result = CallAddUniqueMembers(ardb, source);
            Assert.IsFalse(result.WasMemberAdded[0].Value);
            Assert.AreEqual(ardbCountFirstAdd, ardb.Count);

            // Add a namespace with a private class; verify nothing added
            source = PackageDatabaseTests.BuildDefaultSample("V3");
            MutableSymbol diagnostics = source.MutableRoot.FindByFullName(BuildDiagnosticsNamespaceFor(source.Identity.PackageName), PackageDatabaseTests.SEPARATOR_CHAR);
            MutableSymbol internalNs  = diagnostics.AddChild(new MutableSymbol("Internal", SymbolType.Namespace));

            internalNs.AddChild(new MutableSymbol("Tracer", SymbolType.Class)
            {
                Modifiers = SymbolModifier.Internal
            });
            result = CallAddUniqueMembers(ardb, source);
            Assert.IsFalse(result.WasMemberAdded[0].Value);
            Assert.AreEqual(ardbCountFirstAdd, ardb.Count);

            // Add a new public class (existing namespace); verify it is added
            source      = PackageDatabaseTests.BuildDefaultSample("V4");
            diagnostics = source.MutableRoot.FindByFullName(BuildDiagnosticsNamespaceFor(source.Identity.PackageName), PackageDatabaseTests.SEPARATOR_CHAR);
            diagnostics.AddChild(new MutableSymbol("TraceWatch", SymbolType.Class)
            {
                Modifiers = SymbolModifier.Public | SymbolModifier.Static
            });
            result = CallAddUniqueMembers(ardb, source);
            Assert.IsTrue(result.WasMemberAdded[0].Value);
            Assert.IsTrue(result.WasMemberAdded[result.WasMemberAdded.Length - 1].Value);
            Assert.AreNotEqual(ardbCountFirstAdd, ardb.Count);

            // Verify a query [expect Diagnostics. to match Logger, Memory, and TraceWatch
            ardb.ConvertToImmutable();
            VerifyQueryResults(ardb, version);

            // Double-convert ARDB. Verify queries still work correctly.
            ardb.ConvertToImmutable();
            VerifyQueryResults(ardb, version);

            // Round trip to string; verify query still right, count matches
            string sampleArdbFilePath = "Sample.ardb.txt";

            Write.ToFile(ardb.WriteText, sampleArdbFilePath);
            AddReferenceDatabase reloaded = new AddReferenceDatabase(version);

            Read.FromFile(reloaded.ReadText, sampleArdbFilePath);

            VerifyQueryResults(reloaded, version);
            Assert.AreEqual(ardb.Count, reloaded.Count);

            string sampleRewriteArdbFilePath = "Sample.Rewrite.ardb.txt";

            Write.ToFile(reloaded.WriteText, sampleRewriteArdbFilePath);
            Assert.AreEqual(File.ReadAllText(sampleArdbFilePath), File.ReadAllText(sampleRewriteArdbFilePath));
        }