From d9f1bb1f95c0d1f32e87528e8c98998489774a3c Mon Sep 17 00:00:00 2001 From: t-espave Date: Thu, 11 Aug 2011 16:27:54 -0700 Subject: (phone) cancel/navigation on back key is now deep through calls. More info reported at end of analysis --- BCT/BCT.sln | 40 +++++++++++- BCT/BytecodeTranslator/BytecodeTranslator.csproj | 4 ++ BCT/BytecodeTranslator/ExpressionTraverser.cs | 1 - .../Phone/PhoneBackKeyCallbackTraverser.cs | 32 +++++++--- BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs | 62 ++++++++++++++++-- .../Phone/PhoneNavigationTraverser.cs | 73 +++++++++++++--------- BCT/BytecodeTranslator/Program.cs | 68 ++++++++++++++------ 7 files changed, 216 insertions(+), 64 deletions(-) (limited to 'BCT') diff --git a/BCT/BCT.sln b/BCT/BCT.sln index 7e794a0f..23c219c9 100644 --- a/BCT/BCT.sln +++ b/BCT/BCT.sln @@ -50,9 +50,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdbWriter", "..\..\CCICodeB EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Contracts", "..\..\CCICodeBox\Microsoft.Contracts\Microsoft.Contracts.csproj", "{B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILGarbageCollect", "..\..\CCICodeBox\Samples\ILGarbageCollect\ILGarbageCollect.csproj", "{60CD0C85-1E4A-4068-A4EC-D15B7981A908}" +EndProject Global GlobalSection(TeamFoundationVersionControl) = preSolution - SccNumberOfProjects = 15 + SccNumberOfProjects = 16 SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} SccTeamFoundationServer = http://vstfcodebox:8080/tfs/psi SccProjectUniqueName0 = ..\\..\\CCICodeBox\\CoreObjectModel\\CodeModel\\CodeModel.csproj @@ -130,6 +132,11 @@ Global SccAuxPath14 = http://vstfcodebox:8080/tfs/psi SccLocalPath14 = ..\\..\\CCICodeBox\\Microsoft.Contracts SccProvider14 = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} + SccProjectUniqueName15 = ..\\..\\CCICodeBox\\Samples\\ILGarbageCollect\\ILGarbageCollect.csproj + SccProjectName15 = $/cci/Samples/ILGarbageCollect + SccAuxPath15 = http://vstfcodebox:8080/tfs/psi + SccLocalPath15 = ..\\..\\CCICodeBox\\Samples\\ILGarbageCollect + SccProvider15 = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = BCT.vsmdi @@ -755,6 +762,37 @@ Global {B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}.Release|Mixed Platforms.Build.0 = Release|Any CPU {B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}.Release|x86.ActiveCfg = Release|Any CPU + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.CompilerOnly|Any CPU.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.CompilerOnly|Mixed Platforms.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.CompilerOnly|Mixed Platforms.Build.0 = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.CompilerOnly|x86.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.CompilerOnly|x86.Build.0 = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Debug|x86.ActiveCfg = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Debug|x86.Build.0 = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.FastpathSim|Any CPU.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.FastpathSim|Mixed Platforms.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.FastpathSim|Mixed Platforms.Build.0 = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.FastpathSim|x86.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.FastpathSim|x86.Build.0 = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyDebug|Any CPU.ActiveCfg = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyDebug|Mixed Platforms.ActiveCfg = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyDebug|Mixed Platforms.Build.0 = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyDebug|x86.ActiveCfg = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyDebug|x86.Build.0 = Debug|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyRelease|Any CPU.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyRelease|Mixed Platforms.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyRelease|Mixed Platforms.Build.0 = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyRelease|x86.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.NightlyRelease|x86.Build.0 = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Release|Any CPU.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Release|Mixed Platforms.Build.0 = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Release|x86.ActiveCfg = Release|x86 + {60CD0C85-1E4A-4068-A4EC-D15B7981A908}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/BCT/BytecodeTranslator/BytecodeTranslator.csproj b/BCT/BytecodeTranslator/BytecodeTranslator.csproj index 3bc2c6db..f64ba3a7 100644 --- a/BCT/BytecodeTranslator/BytecodeTranslator.csproj +++ b/BCT/BytecodeTranslator/BytecodeTranslator.csproj @@ -186,6 +186,10 @@ {34B9A0CE-DF18-4CBC-8F7A-90C2B74338D5} PeReader + + {60CD0C85-1E4A-4068-A4EC-D15B7981A908} + ILGarbageCollect + {8C242D42-9714-440F-884D-F64F09E78C7B} TranslationPlugins diff --git a/BCT/BytecodeTranslator/ExpressionTraverser.cs b/BCT/BytecodeTranslator/ExpressionTraverser.cs index 6a054c9c..44ddaf36 100644 --- a/BCT/BytecodeTranslator/ExpressionTraverser.cs +++ b/BCT/BytecodeTranslator/ExpressionTraverser.cs @@ -568,7 +568,6 @@ namespace BytecodeTranslator if (PhoneCodeHelper.instance().isMethodKnownUIChanger(methodCall)) { Bpl.AssumeCmd assumeFalse = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.LiteralExpr.False); this.StmtTraverser.StmtBuilder.Add(assumeFalse); - // FEEDBACK TODO make sure that the call to this method (not the called one but the one in context) is inlined (how?) } } } diff --git a/BCT/BytecodeTranslator/Phone/PhoneBackKeyCallbackTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneBackKeyCallbackTraverser.cs index 3d1ba94a..026cf301 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneBackKeyCallbackTraverser.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneBackKeyCallbackTraverser.cs @@ -28,17 +28,18 @@ namespace BytecodeTranslator.Phone { bool delegateIsAnonymous = false; PhoneCodeHelper.instance().OnBackKeyPressOverriden = true; IBlockStatement delegateBody = null; + IMethodDefinition delegateMethodRef= null; if (methodCall.Arguments.Count() == 1) { IExpression delegateArg= methodCall.Arguments.First(); ICreateDelegateInstance localDelegate = delegateArg as ICreateDelegateInstance; if (localDelegate != null) { delegateIsIdentified = true; - IMethodDefinition delegateRef = localDelegate.MethodToCallViaDelegate.ResolvedMethod; - SourceMethodBody body= delegateRef.Body as SourceMethodBody; + delegateMethodRef = localDelegate.MethodToCallViaDelegate.ResolvedMethod; + SourceMethodBody body= delegateMethodRef.Body as SourceMethodBody; if (body != null) delegateBody = body.Block; - PhoneCodeHelper.instance().KnownBackKeyHandlers.Add(delegateRef); + PhoneCodeHelper.instance().KnownBackKeyHandlers.Add(delegateMethodRef); } AnonymousDelegate anonDelegate = delegateArg as AnonymousDelegate; @@ -56,22 +57,33 @@ namespace BytecodeTranslator.Phone { ICollection navTargets; parseBlockForNavigation(delegateBody, out navigates, out navTargets); if (navigates) { - ICollection targets = null; - PhoneCodeHelper.instance().BackKeyPressNavigates = true; + ICollection> targets = null; if (!PhoneCodeHelper.instance().BackKeyNavigatingOffenders.TryGetValue(typeBeingTraversed, out targets)) { - targets = new HashSet(); + targets = new HashSet>(); } - foreach (string tgt in navTargets) - targets.Add("\"" + tgt + "\""); + foreach (string tgt in navTargets) { + IMethodReference dummyRef=null; + if (delegateIsAnonymous) { + dummyRef = new Microsoft.Cci.MutableCodeModel.MethodReference(); + (dummyRef as Microsoft.Cci.MutableCodeModel.MethodReference).ContainingType= typeBeingTraversed; + (dummyRef as Microsoft.Cci.MutableCodeModel.MethodReference).Name = Dummy.Name; + } + targets.Add(Tuple.Create((delegateIsAnonymous ? dummyRef : delegateMethodRef), "\"" + tgt + "\"")); + } PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeBeingTraversed] = targets; } parseBlockForEventCancellation(delegateBody, out cancelsNav); if (cancelsNav) { - PhoneCodeHelper.instance().BackKeyPressHandlerCancels = true; - PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(typeBeingTraversed); + string reason= "(via delegate "; + if (delegateIsIdentified) + reason += delegateMethodRef.ContainingType.ToString() + "." + delegateMethodRef.Name.Value; + else + reason += "anonymous"; + reason += ")"; + PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(Tuple.Create(typeBeingTraversed, reason)); } } } diff --git a/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs b/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs index 623ddcc4..18107ac2 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs @@ -7,6 +7,7 @@ using Bpl=Microsoft.Boogie; using TranslationPlugins; using Microsoft.Cci.MutableCodeModel; using System.IO; +using ILGarbageCollect; namespace BytecodeTranslator.Phone { public static class UriHelper { @@ -252,13 +253,15 @@ namespace BytecodeTranslator.Phone { public static readonly string[] NAV_CALLS = { /*"GoBack", "GoForward", "Navigate", "StopLoading"*/ "Navigate", "GoBack" }; public bool OnBackKeyPressOverriden { get; set; } - public bool BackKeyPressHandlerCancels { get; set; } - public bool BackKeyPressNavigates { get; set; } + public bool BackKeyPressHandlerCancels { get { return BackKeyCancellingOffenders.Count > 0; } } + public bool BackKeyPressNavigates { get { return BackKeyNavigatingOffenders.Keys.Count > 0; } } public bool BackKeyHandlerOverridenByUnknownDelegate { get; set; } - public ICollection BackKeyCancellingOffenders { get; set; } + public ICollection> BackKeyCancellingOffenders { get; set; } public ICollection BackKeyUnknownDelegateOffenders { get; set; } - public Dictionary> BackKeyNavigatingOffenders { get; set; } + public Dictionary>> BackKeyNavigatingOffenders { get; set; } public ICollection KnownBackKeyHandlers { get; set; } + public ICollection KnownNavigatingMethods { get; set; } + public ICollection KnownEventCancellingMethods { get; set; } private Dictionary PHONE_UI_CHANGER_METHODS; @@ -288,10 +291,12 @@ namespace BytecodeTranslator.Phone { platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType; initializeKnownUIChangers(); - BackKeyCancellingOffenders= new HashSet(); + BackKeyCancellingOffenders= new HashSet>(); BackKeyUnknownDelegateOffenders = new HashSet(); - BackKeyNavigatingOffenders = new Dictionary>(); + BackKeyNavigatingOffenders = new Dictionary>>(); KnownBackKeyHandlers = new HashSet(); + KnownNavigatingMethods = new HashSet(); + KnownEventCancellingMethods = new HashSet(); } } @@ -803,5 +808,50 @@ namespace BytecodeTranslator.Phone { return isBackKeyPressOverride(method.ResolvedMethod) || KnownBackKeyHandlers.Contains(method); } + + internal IEnumerable getIndirectNavigators(IEnumerable modules, IMethodReference method) { + IEnumerable reachable = getReachableMethodsFromMethod(method, modules); + reachable= reachable.Except(new IMethodDefinition[] { method.ResolvedMethod }); + return getResolvedMethods(KnownNavigatingMethods).Intersect(reachable); + } + + internal IEnumerable getIndirectCancellations(IEnumerable modules, IMethodReference method) { + IEnumerable reachable = getReachableMethodsFromMethod(method, modules); + reachable = reachable.Except(new IMethodDefinition[] { method.ResolvedMethod }); + return getResolvedMethods(KnownEventCancellingMethods).Intersect(reachable); + } + + internal IEnumerable getReachableMethodsFromMethod(IMethodReference method, IEnumerable modules) { + IEnumerable assemblies = getAssembliesFromModules(modules); + Microsoft.Cci.MetadataReaderHost readerHost = host as Microsoft.Cci.MetadataReaderHost; + + if (readerHost == null) + return new List(); //? + + ILGarbageCollect.Mark.WholeProgram program = new ILGarbageCollect.Mark.WholeProgram(assemblies, readerHost); + RapidTypeAnalysis analyzer = new RapidTypeAnalysis(program, TargetProfile.Phone); + analyzer.Run(new IMethodReference[] { method }); + return analyzer.ReachableMethods(); + } + + internal IEnumerable getAssembliesFromModules(IEnumerable modules) { + IList assemblies = new List(); + foreach (IModule module in modules) { + IAssembly assembly = module as IAssembly; + if (assembly != null) + assemblies.Add(assembly); + } + + return assemblies; + } + + internal IEnumerable getResolvedMethods(IEnumerable methRefs) { + IList methDefs = new List(); + foreach (IMethodReference methRef in methRefs) { + methDefs.Add(methRef.ResolvedMethod); + } + + return methDefs; + } } } diff --git a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs index 37cd83c0..a5571efa 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs @@ -16,10 +16,16 @@ namespace BytecodeTranslator.Phone { private static HashSet navCallers= new HashSet(); public static IEnumerable NavCallers { get { return navCallers; } } - public PhoneNavigationCodeTraverser(MetadataReaderHost host, ITypeReference typeTraversed, IMethodDefinition methodTraversed) : base() { + private HashSet navigationCallers; + public IEnumerable NavigationCallers { get { return NavigationCallers; } } + + public PhoneNavigationCodeTraverser(MetadataReaderHost host, IEnumerable assemblies) : base() { this.host = host; - this.typeTraversed = typeTraversed; - this.methodTraversed = methodTraversed; + List assembliesTraversed = new List(); + foreach (IAssemblyReference asmRef in assemblies) { + assembliesTraversed.Add(asmRef.ResolvedAssembly); + } + Microsoft.Cci.Immutable.PlatformType platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType; // TODO obtain version, culture and signature data dynamically @@ -29,15 +35,18 @@ namespace BytecodeTranslator.Phone { assembly = PhoneTypeHelper.getSystemAssemblyReference(host); cancelEventArgsType = platform.CreateReference(assembly, "System", "ComponentModel", "CancelEventArgs"); + navigationCallers = new HashSet(); } - public override void Visit(IEnumerable assemblyReferences) { - base.Visit(assemblyReferences); + public override void Visit(ITypeDefinition typeDef) { + this.typeTraversed = typeDef; + base.Visit(typeDef); } - public override void Visit(IMethodDefinition method) { + this.methodTraversed = method; if (method.IsConstructor && PhoneTypeHelper.isPhoneApplicationClass(typeTraversed, host)) { + navigationCallers.Add(method); string mainPageUri = PhoneCodeHelper.instance().PhonePlugin.getMainPageXAML(); SourceMethodBody sourceBody = method.Body as SourceMethodBody; if (sourceBody != null) { @@ -130,14 +139,21 @@ namespace BytecodeTranslator.Phone { if (!PhoneCodeHelper.instance().isBackKeyPressOverride(methodTraversed.ResolvedMethod)) return false; + return isEventCancellationMethodCall(call); + } + + private bool isEventCancellationMethodCall(IMethodCall call) { if (!call.MethodToCall.Name.Value.StartsWith("set_Cancel")) return false; if (call.Arguments.Count() != 1 || call.Arguments.ToList()[0].Type != host.PlatformType.SystemBoolean) return false; + if (call.ThisArgument == null || !call.ThisArgument.Type.isCancelEventArgsClass(host)) + return false; + ICompileTimeConstant constant = call.Arguments.ToList()[0] as ICompileTimeConstant; - if (constant != null && constant.Value != null ) { + if (constant != null && constant.Value != null) { CompileTimeConstant falseConstant = new CompileTimeConstant() { Type = host.PlatformType.SystemBoolean, Value = false, @@ -151,25 +167,22 @@ namespace BytecodeTranslator.Phone { public override void Visit(IMethodCall methodCall) { string target; - - if (PhoneCodeHelper.instance().isKnownBackKeyOverride(methodTraversed)) { - // NAVIGATION TODO this is turning into a mess, I'd like to decouple both traversals - return; // we already seen this - } - if (isNavigationOnBackKeyPressHandler(methodCall, out target)) { - PhoneCodeHelper.instance().BackKeyPressNavigates = true; - ICollection targets; + ICollection> targets; try { targets= PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed]; } catch (KeyNotFoundException) { - targets = new HashSet(); + targets = new HashSet>(); } - targets.Add("\"" + target + "\""); + targets.Add(Tuple.Create(methodTraversed, "\"" + target + "\"")); PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed]= targets; } else if (isCancelOnBackKeyPressHandler(methodCall)) { - PhoneCodeHelper.instance().BackKeyPressHandlerCancels = true; - PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(typeTraversed); + PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(Tuple.Create(typeTraversed,"")); + } + + // re-check whether it is an event cancellation call + if (isEventCancellationMethodCall(methodCall)) { + PhoneCodeHelper.instance().KnownEventCancellingMethods.Add(methodTraversed); } // check whether it is a NavigationService call @@ -215,6 +228,11 @@ namespace BytecodeTranslator.Phone { } } + if (navCallFound && !navCallIsBack) { + // check this method as a navigation method + PhoneCodeHelper.instance().KnownNavigatingMethods.Add(methodTraversed); + } + //Console.Write("Page navigation event found. Target is static? " + (isStatic ? "YES" : "NO")); //if (!isStatic) { // Console.WriteLine(" -- Reason: " + notStaticReason); @@ -301,18 +319,16 @@ namespace BytecodeTranslator.Phone { public class PhoneNavigationMetadataTraverser : BaseMetadataTraverser { private MetadataReaderHost host; private ITypeDefinition typeBeingTraversed; + private PhoneNavigationCodeTraverser codeTraverser; public PhoneNavigationMetadataTraverser(MetadataReaderHost host) : base() { this.host = host; } - public override void Visit(IModule module) { - base.Visit(module); - } - - public override void Visit(IAssembly assembly) { - base.Visit(assembly); + public override void Visit(IEnumerable assemblies) { + codeTraverser = new PhoneNavigationCodeTraverser(host, assemblies); + base.Visit(assemblies); } // TODO can we avoid visiting every type? Are there only a few, identifiable, types that may perform navigation? @@ -334,17 +350,18 @@ namespace BytecodeTranslator.Phone { mutableTypeDef.Fields.Add(fieldDef); } } + + codeTraverser.Visit(typeDefinition); base.Visit(typeDefinition); } // TODO same here. Are there specific methods (and ways to identfy those) that can perform navigation? public override void Visit(IMethodDefinition method) { if (PhoneCodeHelper.instance().isBackKeyPressOverride(method)) { + PhoneCodeHelper.instance().KnownBackKeyHandlers.Add(method); PhoneCodeHelper.instance().OnBackKeyPressOverriden = true; } - - PhoneNavigationCodeTraverser codeTraverser = new PhoneNavigationCodeTraverser(host, typeBeingTraversed, method); - codeTraverser.Visit(method); + base.Visit(method); } public void InjectPhoneCodeAssemblies(IEnumerable assemblies) { diff --git a/BCT/BytecodeTranslator/Program.cs b/BCT/BytecodeTranslator/Program.cs index 63d96e5d..7779b76d 100644 --- a/BCT/BytecodeTranslator/Program.cs +++ b/BCT/BytecodeTranslator/Program.cs @@ -5,6 +5,7 @@ //----------------------------------------------------------------------------- using System; +using System.Linq; using System.IO; using Microsoft.Cci; using Microsoft.Cci.MetadataReader; @@ -171,6 +172,7 @@ namespace BytecodeTranslator { return result; } + private static List modules; public static int TranslateAssembly(List assemblyNames, HeapFactory heapFactory, Options options, List exemptionList, bool whiteList) { Contract.Requires(assemblyNames != null); Contract.Requires(heapFactory != null); @@ -185,7 +187,7 @@ namespace BytecodeTranslator { var host = new CodeContractAwareHostEnvironment(libPaths != null ? libPaths : Enumerable.Empty, true, true); Host = host; - var modules = new List(); + modules = new List(); var contractExtractors = new Dictionary(); var pdbReaders = new Dictionary(); foreach (var a in assemblyNames) { @@ -298,16 +300,18 @@ namespace BytecodeTranslator { } if (PhoneCodeHelper.instance().PhoneFeedbackToggled || PhoneCodeHelper.instance().PhoneNavigationToggled) { - PhoneBackKeyCallbackTraverser traverser = new PhoneBackKeyCallbackTraverser(sink.host); - traverser.Visit(modules); - PhoneMethodInliningMetadataTraverser inlineTraverser = new PhoneMethodInliningMetadataTraverser(PhoneCodeHelper.instance()); inlineTraverser.findAllMethodsToInline(modules); PhoneCodeHelper.updateInlinedMethods(sink, inlineTraverser.getMethodsToInline()); System.Console.WriteLine("Total methods seen: {0}, inlined: {1}", inlineTraverser.TotalMethodsCount, inlineTraverser.InlinedMethodsCount); + + PhoneBackKeyCallbackTraverser traverser = new PhoneBackKeyCallbackTraverser(sink.host); + traverser.Visit(modules); + } + // NAVIGATION TODO: refactor warnings out of here if (PhoneCodeHelper.instance().PhoneNavigationToggled) { string outputConfigFile = Path.ChangeExtension(phoneControlsConfigFile, "bplout"); StreamWriter outputStream = new StreamWriter(outputConfigFile); @@ -315,6 +319,42 @@ namespace BytecodeTranslator { outputStream.Close(); PhoneCodeWrapperWriter.createCodeWrapper(sink); + foreach (IMethodReference navMethod in PhoneCodeHelper.instance().KnownBackKeyHandlers) { + // right now we traversed everything so we can see reachability + IEnumerable indirects= PhoneCodeHelper.instance().getIndirectNavigators(modules, navMethod); + if (indirects.Count() > 0) { + ICollection> targets = null; + PhoneCodeHelper.instance().BackKeyNavigatingOffenders.TryGetValue(navMethod.ContainingType, out targets); + if (targets == null) { + targets = new HashSet>(); + } + string indirectTargeting = " via ("; + foreach (IMethodDefinition methDef in indirects) { + indirectTargeting += methDef.ContainingType.ToString() + "." + methDef.Name.Value + ", "; + } + indirectTargeting += ")"; + targets.Add(Tuple.Create(navMethod, indirectTargeting)); + PhoneCodeHelper.instance().BackKeyNavigatingOffenders[navMethod.ContainingType] = targets; + } + + indirects = PhoneCodeHelper.instance().getIndirectCancellations(modules, navMethod); + if (indirects.Count() > 0) { + string indirectTargeting = "("; + foreach (IMethodDefinition methDef in indirects) { + indirectTargeting += methDef.ContainingType.ToString() + "." + methDef.Name.Value + ", "; + } + indirectTargeting += ")"; + PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(Tuple.Create(navMethod.ContainingType, indirectTargeting)); + } + } + + foreach (IMethodDefinition def in PhoneNavigationCodeTraverser.NavCallers) { + if (!PhoneCodeHelper.instance().isKnownBackKeyOverride(def)) + PhoneCodeHelper.instance().addHandlerStubCaller(sink, def); + } + PhoneCodeHelper.instance().addNavigationUriHavocer(sink); + PhoneCodeHelper.instance().createQueriesBatchFile(sink, outputFileName); + // NAVIGATION TODO for now I console this out if (!PhoneCodeHelper.instance().OnBackKeyPressOverriden) { Console.Out.WriteLine("No back navigation issues, OnBackKeyPress is not overriden"); @@ -330,31 +370,23 @@ namespace BytecodeTranslator { if (PhoneCodeHelper.instance().BackKeyPressNavigates) { Console.Out.WriteLine("Back navigation ISSUE: back key press may navigate to pages not in backstack! From pages:"); foreach (ITypeReference type in PhoneCodeHelper.instance().BackKeyNavigatingOffenders.Keys) { - ICollection targets = PhoneCodeHelper.instance().BackKeyNavigatingOffenders[type]; + ICollection> targets = PhoneCodeHelper.instance().BackKeyNavigatingOffenders[type]; Console.WriteLine("\t" + type.ToString() + " may navigate to "); - foreach (string target in targets) { - Console.WriteLine("\t\t" + target); + foreach (Tuple target in targets) { + Console.WriteLine("\t\t" + target.Item2 + " via " + + (target.Item1.Name == Dummy.Name ? "anonymous delegate" : target.Item1.ContainingType.ToString() + "." + target.Item1.Name.Value)); } } } if (PhoneCodeHelper.instance().BackKeyPressHandlerCancels) { Console.Out.WriteLine("Back navigation ISSUE: back key press default behaviour may be cancelled! From pages:"); - foreach (ITypeReference type in PhoneCodeHelper.instance().BackKeyCancellingOffenders) { - Console.WriteLine("\t" + type.ToString()); + foreach (Tuple cancellation in PhoneCodeHelper.instance().BackKeyCancellingOffenders) { + Console.WriteLine("\t" + cancellation.Item1.ToString() + " via " + cancellation.Item2); } } } } - - if (PhoneCodeHelper.instance().PhoneNavigationToggled) { - foreach (IMethodDefinition def in PhoneNavigationCodeTraverser.NavCallers) { - if (!PhoneCodeHelper.instance().isKnownBackKeyOverride(def)) - PhoneCodeHelper.instance().addHandlerStubCaller(sink, def); - } - PhoneCodeHelper.instance().addNavigationUriHavocer(sink); - PhoneCodeHelper.instance().createQueriesBatchFile(sink, outputFileName); - } } private static string NameUpToFirstPeriod(string name) { -- cgit v1.2.3