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; }
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); } }
private static void SendLeaderBoardRewriterFeature(FoxtrotOptions options) { #if LeaderBoard LeaderBoard.LeaderBoardAPI.SendLeaderBoardFeatureUse(LeaderBoardFeature(options)); #endif }