示例#1
0
        private static int LeaderBoardFeature(FoxtrotOptions options)
        {
            Contract.Requires(options != null);

            var result = options.level | LeaderBoardFeatureMask_Rewriter;
            if (options.assemblyMode == FoxtrotOptions.AssemblyMode.standard)
            {
                result |= (int) LeaderBoardFeatureId.StandardMode;
            }

            if (options.throwOnFailure)
            {
                result |= (int) LeaderBoardFeatureId.ThrowOnFailure;
            }

            return result;
        }
示例#2
0
        private static int InternalMain(string[] args)
        {
            options = new FoxtrotOptions();
            options.Parse(args);

            if (!options.nologo)
            {
                var version = typeof (FoxtrotOptions).Assembly.GetName().Version;

                Console.WriteLine("Microsoft (R) .NET Contract Rewriter Version {0}", version);
                Console.WriteLine("Copyright (C) Microsoft Corporation. All rights reserved.");
                Console.WriteLine("");
            }

            if (options.HasErrors)
            {
                options.PrintErrorsAndExit(Console.Out);
                return -1;
            }
            if (options.HelpRequested)
            {
                options.PrintOptions("", Console.Out);
                return 0;
            }

            if (options.breakIntoDebugger)
            {
                Debugger.Launch();
            }

#if DEBUG
            if (options.nobox)
            {
                Debug.Listeners.Clear();

                // listen for failed assertions
                Debug.Listeners.Add(new ExitTraceListener());
            }
#else
      Debug.Listeners.Clear();
#endif

            if (options.repro)
            {
                WriteReproFile(args);
            }

            var resolver = new AssemblyResolver(
                options.resolvedPaths, options.libpaths, options.debug,
                options.shortBranches, options.verbose > 2,
                PostLoadExtractionHook);

            GlobalAssemblyCache.probeGAC = options.useGAC;

            // Connect to LeaderBoard

            SendLeaderBoardRewriterFeature(options);

            int errorReturnValue = -1;

            IDictionary assemblyCache = new Hashtable();

            // Trigger static initializer of SystemTypes
            var savedGACFlag = GlobalAssemblyCache.probeGAC;
            
            GlobalAssemblyCache.probeGAC = false;
            
            TypeNode dummy = SystemTypes.Object;

            TargetPlatform.Clear();
            TargetPlatform.AssemblyReferenceFor = null;
            GlobalAssemblyCache.probeGAC = savedGACFlag;

            try
            {
                // Validate the command-line arguments.

                if (options.output != "same")
                {
                    if (!Path.IsPathRooted(options.output))
                    {
                        string s = Directory.GetCurrentDirectory();
                        options.output = Path.Combine(s, options.output);
                    }
                }

                if (options.assembly == null && options.GeneralArguments.Count == 1)
                {
                    options.assembly = options.GeneralArguments[0];
                }

                if (!File.Exists(options.assembly))
                {
                    throw new FileNotFoundException(String.Format("The given assembly '{0}' does not exist.", options.assembly));
                }

                InitializePlatform(resolver, assemblyCache);

                if (options.passthrough)
                {
                    options.rewrite = false;
                }
                if (!(options.rewrite || options.passthrough))
                {
                    Console.WriteLine("Error: Need to specify at least one of: /rewrite, /pass");
                    options.PrintOptions("", Console.Out);

                    return errorReturnValue;
                }

                if (options.extractSourceText && !options.debug)
                {
                    Console.WriteLine("Error: Cannot specify /sourceText without also specifying /debug");
                    options.PrintOptions("", Console.Out);

                    return errorReturnValue;
                }

                if (!(0 <= options.level && options.level <= 4))
                {
                    Console.WriteLine("Error: incorrect /level: {0}. /level must be between 0 and 4 (inclusive)", options.level);
                    return errorReturnValue;
                }

                if (options.automaticallyLookForOOBs && options.contracts != null && 0 < options.contracts.Count)
                {
                    Console.WriteLine("Error: Out of band contracts are being automatically applied, all files specified using the contracts option are ignored.");
                    return errorReturnValue;
                }

                // Sanity check: just make sure that all files specified for out-of-band contracts actually exist
                bool atLeastOneOobNotFound = false;
                if (options.contracts != null)
                {
                    foreach (string oob in options.contracts)
                    {
                        bool found = false;
                        if (File.Exists(oob)) found = true;

                        if (!found)
                        {
                            if (options.libpaths != null)
                            {
                                foreach (string dir in options.libpaths)
                                {
                                    if (File.Exists(Path.Combine(dir, oob)))
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                            }

                            if (!found)
                            {
                                Console.WriteLine("Error: Contract file '" + oob + "' could not be found");
                                atLeastOneOobNotFound = true;
                            }
                        }
                    }
                }

                if (atLeastOneOobNotFound)
                {
                    return errorReturnValue;
                }

                // Load the assembly to be rewritten

                originalAssemblyName = Path.GetFileNameWithoutExtension(options.assembly);
                AssemblyNode assemblyNode = AssemblyNode.GetAssembly(options.assembly,
                    TargetPlatform.StaticAssemblyCache, true, options.debug, true, options.shortBranches
                    , delegate(AssemblyNode a)
                    {
                        //Console.WriteLine("Loaded '" + a.Name + "' from '" + a.Location.ToString() + "'");
                        PossiblyLoadOOB(resolver, a, originalAssemblyName);
                    });

                if (assemblyNode == null)
                    throw new FileLoadException("The given assembly could not be loaded.", options.assembly);

                // Check to see if any metadata errors were reported

                if (assemblyNode.MetadataImportWarnings != null && assemblyNode.MetadataImportWarnings.Count > 0)
                {
                    string msg = "\tThere were warnings reported in " + assemblyNode.Name + "'s metadata.\n";
                    foreach (Exception e in assemblyNode.MetadataImportWarnings)
                    {
                        msg += "\t" + e.Message;
                    }

                    Console.WriteLine(msg);
                }

                if (assemblyNode.MetadataImportErrors != null && assemblyNode.MetadataImportErrors.Count > 0)
                {
                    string msg = "\tThere were errors reported in " + assemblyNode.Name + "'s metadata.\n";
                    foreach (Exception e in assemblyNode.MetadataImportErrors)
                    {
                        msg += "\t" + e.Message;
                    }

                    Console.WriteLine(msg);

                    throw new InvalidOperationException("Foxtrot: " + msg);
                }
                else
                {
                    //Console.WriteLine("\tThere were no errors reported in {0}'s metadata.", assemblyNode.Name);
                }

                // Load the rewriter assembly if any

                AssemblyNode rewriterMethodAssembly = null;
                if (options.rewriterMethods != null && 0 < options.rewriterMethods.Length)
                {
                    string[] pieces = options.rewriterMethods.Split(',');
                    if (!(pieces.Length == 2 || pieces.Length == 3))
                    {
                        Console.WriteLine("Error: Need to provide two or three comma separated arguments to /rewriterMethods");
                        options.PrintOptions("", Console.Out);

                        return errorReturnValue;
                    }

                    string assemName = pieces[0];
                    rewriterMethodAssembly = resolver.ProbeForAssembly(assemName, null, resolver.AllExt);
                    if (rewriterMethodAssembly == null)
                    {
                        Console.WriteLine("Error: Could not open assembly '" + assemName + "'");
                        return errorReturnValue;
                    }

                    string nameSpaceName = null;
                    string bareClassName = null;

                    if (pieces.Length == 2)
                    {
                        // interpret A.B.C as namespace A.B and class C
                        // no nested classes allowed.
                        string namespaceAndClassName = pieces[1];

                        int lastDot = namespaceAndClassName.LastIndexOf('.');

                        nameSpaceName = lastDot == -1 ? "" : namespaceAndClassName.Substring(0, lastDot);
                        bareClassName = namespaceAndClassName.Substring(lastDot + 1);

                        userSpecifiedContractType = rewriterMethodAssembly.GetType(Identifier.For(nameSpaceName),
                            Identifier.For(bareClassName));
                    }
                    else
                    {
                        // pieces.Length == 3
                        // namespace can be A.B and class can be C.D
                        nameSpaceName = pieces[1];
                        bareClassName = pieces[2];
                        userSpecifiedContractType = GetPossiblyNestedType(rewriterMethodAssembly, nameSpaceName, bareClassName);
                    }

                    if (userSpecifiedContractType == null)
                    {
                        Console.WriteLine("Error: Could not find type '" + bareClassName + "' in the namespace '" +
                                          nameSpaceName + "' in the assembly '" + assemName + "'");

                        return errorReturnValue;
                    }
                }

                // Load the ASTs for all of the contract methods

                AssemblyNode contractAssembly = null;
                if (!options.passthrough)
                {
                    // The contract assembly should be determined in the following order:
                    // 0. if the option contractLibrary was specified, use that.
                    // 1. the assembly being rewritten
                    // 2. the system assembly
                    // 3. the microsoft.contracts library

                    if (options.contractLibrary != null)
                    {
                        contractAssembly = resolver.ProbeForAssembly(options.contractLibrary,
                            Path.GetDirectoryName(options.assembly), resolver.EmptyAndDllExt);

                        if (contractAssembly != null)
                            DefaultContractLibrary = ContractNodes.GetContractNodes(contractAssembly, options.EmitError);

                        if (contractAssembly == null || DefaultContractLibrary == null)
                        {
                            Console.WriteLine("Error: could not load Contracts API from assembly '{0}'", options.contractLibrary);
                            return -1;
                        }
                    }
                    else
                    {
                        if (DefaultContractLibrary == null)
                        {
                            // See if contracts are in the assembly we're rewriting
                            DefaultContractLibrary = ContractNodes.GetContractNodes(assemblyNode, options.EmitError);
                        }

                        if (DefaultContractLibrary == null)
                        {
                            // See if contracts are in Mscorlib
                            DefaultContractLibrary = ContractNodes.GetContractNodes(SystemTypes.SystemAssembly,
                                options.EmitError);
                        }

                        // try to load Microsoft.Contracts.dll
                        var microsoftContractsLibrary = resolver.ProbeForAssembly("Microsoft.Contracts",
                            Path.GetDirectoryName(options.assembly), resolver.DllExt);

                        if (microsoftContractsLibrary != null)
                        {
                            BackupContractLibrary = ContractNodes.GetContractNodes(microsoftContractsLibrary, options.EmitError);
                        }

                        if (DefaultContractLibrary == null && BackupContractLibrary != null)
                        {
                            DefaultContractLibrary = BackupContractLibrary;
                        }
                    }
                }

                if (DefaultContractLibrary == null)
                {
                    if (options.output == "same")
                    {
                        Console.WriteLine(
                            "Warning: Runtime Contract Checking requested, but contract class could not be found. Did you forget to reference the contracts assembly?");

                        return 0; // Returning success so that it doesn't break any build processes.
                    }
                    else
                    {
                        // Then an output file was specified (assume it is not the same as the input assembly, but that could be checked here).
                        // In that case, consider it an error to not have found a contract class.
                        // No prinicpled reason, but this is a common pitfall that several users have run into and the rewriter just 
                        // didn't do anything without giving any reason.
                        Console.WriteLine(
                            "Error: Runtime Contract Checking requested, but contract class could not be found. Did you forget to reference the contracts assembly?");

                        return errorReturnValue;
                    }
                }

                if (0 < options.verbose)
                {
                    Console.WriteLine("Trace: Using '" + DefaultContractLibrary.ContractClass.DeclaringModule.Location +
                                      "' for the definition of the contract class");
                }

                // Make sure we extract contracts from the system assembly and the system.dll assemblies.
                // As they are already loaded, they will never trigger the post assembly load event.
                // But even if we are rewriting one of these assemblies (and so *not* trying to extract
                // the contracts at this point), still need to hook up our resolver to them. If this
                // isn't done, then any references chased down from them might not get resolved.

                bool isPreloadedAssembly = false;

                CheckIfPreloaded(resolver, assemblyNode, SystemTypes.SystemAssembly, ref isPreloadedAssembly);
                CheckIfPreloaded(resolver, assemblyNode, SystemTypes.SystemDllAssembly, ref isPreloadedAssembly);

                //CheckIfPreloaded(resolver, assemblyNode, SystemTypes.SystemRuntimeWindowsRuntimeAssembly, ref isPreloadedAssembly);
                //CheckIfPreloaded(resolver, assemblyNode, SystemTypes.SystemRuntimeWindowsRuntimeUIXamlAssembly, ref isPreloadedAssembly);

                if (!isPreloadedAssembly)
                {
                    assemblyNode.AssemblyReferenceResolution += resolver.ResolveAssemblyReference;
                }

                MikesArchitecture(resolver, assemblyNode, DefaultContractLibrary, BackupContractLibrary);

                return options.GetErrorCount();
            }
            catch (Exception exception)
            {
                SendLeaderBoardFailure();

                // Redirect the exception message to the console and quit.
                Console.Error.WriteLine(new System.CodeDom.Compiler.CompilerError(exception.Source, 0, 0, null, exception.Message));
                return errorReturnValue;
            }
            finally
            {
                // Reset statics

                userSpecifiedContractType = null;
                DefaultContractLibrary = null;
                BackupContractLibrary = null;
                originalAssemblyName = null;
                options = null;

                // eagerly close all assemblies due to pdb file locking issues
                DisposeAssemblies(assemblyCache.Values);

                // copy needed since Dispose actually removes things from the StaticAssemblyCache
                object[] assemblies = new object[TargetPlatform.StaticAssemblyCache.Values.Count];

                TargetPlatform.StaticAssemblyCache.Values.CopyTo(assemblies, 0);
                DisposeAssemblies(assemblies);
            }
        }
示例#3
0
        private static void SendLeaderBoardRewriterFeature(FoxtrotOptions options)
        {
#if LeaderBoard
        LeaderBoard.LeaderBoardAPI.SendLeaderBoardFeatureUse(LeaderBoardFeature(options));
#endif
        }