summaryrefslogtreecommitdiff
path: root/BCT
diff options
context:
space:
mode:
authorGravatar t-espave <unknown>2011-08-11 16:27:54 -0700
committerGravatar t-espave <unknown>2011-08-11 16:27:54 -0700
commitd9f1bb1f95c0d1f32e87528e8c98998489774a3c (patch)
tree01435137bfa71e1690c929e7735f661badb0dc4f /BCT
parenta07b4736446ca4dd8a3af219cef4d05ff07055b9 (diff)
(phone) cancel/navigation on back key is now deep through calls. More info reported at end of analysis
Diffstat (limited to 'BCT')
-rw-r--r--BCT/BCT.sln40
-rw-r--r--BCT/BytecodeTranslator/BytecodeTranslator.csproj4
-rw-r--r--BCT/BytecodeTranslator/ExpressionTraverser.cs1
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneBackKeyCallbackTraverser.cs32
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs62
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs73
-rw-r--r--BCT/BytecodeTranslator/Program.cs68
7 files changed, 216 insertions, 64 deletions
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 @@
<Project>{34B9A0CE-DF18-4CBC-8F7A-90C2B74338D5}</Project>
<Name>PeReader</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\..\CCICodeBox\Samples\ILGarbageCollect\ILGarbageCollect.csproj">
+ <Project>{60CD0C85-1E4A-4068-A4EC-D15B7981A908}</Project>
+ <Name>ILGarbageCollect</Name>
+ </ProjectReference>
<ProjectReference Include="..\TranslationPlugins\TranslationPlugins.csproj">
<Project>{8C242D42-9714-440F-884D-F64F09E78C7B}</Project>
<Name>TranslationPlugins</Name>
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<string> navTargets;
parseBlockForNavigation(delegateBody, out navigates, out navTargets);
if (navigates) {
- ICollection<string> targets = null;
- PhoneCodeHelper.instance().BackKeyPressNavigates = true;
+ ICollection<Tuple<IMethodReference,string>> targets = null;
if (!PhoneCodeHelper.instance().BackKeyNavigatingOffenders.TryGetValue(typeBeingTraversed, out targets)) {
- targets = new HashSet<string>();
+ targets = new HashSet<Tuple<IMethodReference,string>>();
}
- 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<IMethodReference, string>((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<ITypeReference,string>(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<ITypeReference> BackKeyCancellingOffenders { get; set; }
+ public ICollection<Tuple<ITypeReference,string>> BackKeyCancellingOffenders { get; set; }
public ICollection<ITypeReference> BackKeyUnknownDelegateOffenders { get; set; }
- public Dictionary<ITypeReference, ICollection<string>> BackKeyNavigatingOffenders { get; set; }
+ public Dictionary<ITypeReference, ICollection<Tuple<IMethodReference,string>>> BackKeyNavigatingOffenders { get; set; }
public ICollection<IMethodReference> KnownBackKeyHandlers { get; set; }
+ public ICollection<IMethodReference> KnownNavigatingMethods { get; set; }
+ public ICollection<IMethodReference> KnownEventCancellingMethods { get; set; }
private Dictionary<string, string[]> PHONE_UI_CHANGER_METHODS;
@@ -288,10 +291,12 @@ namespace BytecodeTranslator.Phone {
platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType;
initializeKnownUIChangers();
- BackKeyCancellingOffenders= new HashSet<ITypeReference>();
+ BackKeyCancellingOffenders= new HashSet<Tuple<ITypeReference,string>>();
BackKeyUnknownDelegateOffenders = new HashSet<ITypeReference>();
- BackKeyNavigatingOffenders = new Dictionary<ITypeReference, ICollection<string>>();
+ BackKeyNavigatingOffenders = new Dictionary<ITypeReference, ICollection<Tuple<IMethodReference,string>>>();
KnownBackKeyHandlers = new HashSet<IMethodReference>();
+ KnownNavigatingMethods = new HashSet<IMethodReference>();
+ KnownEventCancellingMethods = new HashSet<IMethodReference>();
}
}
@@ -803,5 +808,50 @@ namespace BytecodeTranslator.Phone {
return isBackKeyPressOverride(method.ResolvedMethod) ||
KnownBackKeyHandlers.Contains(method);
}
+
+ internal IEnumerable<IMethodDefinition> getIndirectNavigators(IEnumerable<IModule> modules, IMethodReference method) {
+ IEnumerable<IMethodDefinition> reachable = getReachableMethodsFromMethod(method, modules);
+ reachable= reachable.Except(new IMethodDefinition[] { method.ResolvedMethod });
+ return getResolvedMethods(KnownNavigatingMethods).Intersect(reachable);
+ }
+
+ internal IEnumerable<IMethodDefinition> getIndirectCancellations(IEnumerable<IModule> modules, IMethodReference method) {
+ IEnumerable<IMethodDefinition> reachable = getReachableMethodsFromMethod(method, modules);
+ reachable = reachable.Except(new IMethodDefinition[] { method.ResolvedMethod });
+ return getResolvedMethods(KnownEventCancellingMethods).Intersect(reachable);
+ }
+
+ internal IEnumerable<IMethodDefinition> getReachableMethodsFromMethod(IMethodReference method, IEnumerable<IModule> modules) {
+ IEnumerable<IAssembly> assemblies = getAssembliesFromModules(modules);
+ Microsoft.Cci.MetadataReaderHost readerHost = host as Microsoft.Cci.MetadataReaderHost;
+
+ if (readerHost == null)
+ return new List<IMethodDefinition>(); //?
+
+ 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<IAssembly> getAssembliesFromModules(IEnumerable<IModule> modules) {
+ IList<IAssembly> assemblies = new List<IAssembly>();
+ foreach (IModule module in modules) {
+ IAssembly assembly = module as IAssembly;
+ if (assembly != null)
+ assemblies.Add(assembly);
+ }
+
+ return assemblies;
+ }
+
+ internal IEnumerable<IMethodDefinition> getResolvedMethods(IEnumerable<IMethodReference> methRefs) {
+ IList<IMethodDefinition> methDefs = new List<IMethodDefinition>();
+ 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<IMethodDefinition> navCallers= new HashSet<IMethodDefinition>();
public static IEnumerable<IMethodDefinition> NavCallers { get { return navCallers; } }
- public PhoneNavigationCodeTraverser(MetadataReaderHost host, ITypeReference typeTraversed, IMethodDefinition methodTraversed) : base() {
+ private HashSet<IMethodReference> navigationCallers;
+ public IEnumerable<IMethodReference> NavigationCallers { get { return NavigationCallers; } }
+
+ public PhoneNavigationCodeTraverser(MetadataReaderHost host, IEnumerable<IAssemblyReference> assemblies) : base() {
this.host = host;
- this.typeTraversed = typeTraversed;
- this.methodTraversed = methodTraversed;
+ List<IAssembly> assembliesTraversed = new List<IAssembly>();
+ 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<IMethodReference>();
}
- public override void Visit(IEnumerable<IAssemblyReference> 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<string> targets;
+ ICollection<Tuple<IMethodReference,string>> targets;
try {
targets= PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed];
} catch (KeyNotFoundException) {
- targets = new HashSet<string>();
+ targets = new HashSet<Tuple<IMethodReference,string>>();
}
- targets.Add("\"" + target + "\"");
+ targets.Add(Tuple.Create<IMethodReference,string>(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<ITypeReference, string>(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<IAssemblyReference> 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<IUnit> 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<IModule> modules;
public static int TranslateAssembly(List<string> assemblyNames, HeapFactory heapFactory, Options options, List<Regex> 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<string>.Empty, true, true);
Host = host;
- var modules = new List<IModule>();
+ modules = new List<IModule>();
var contractExtractors = new Dictionary<IUnit, IContractProvider>();
var pdbReaders = new Dictionary<IUnit, PdbReader>();
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<IMethodDefinition> indirects= PhoneCodeHelper.instance().getIndirectNavigators(modules, navMethod);
+ if (indirects.Count() > 0) {
+ ICollection<Tuple<IMethodReference, string>> targets = null;
+ PhoneCodeHelper.instance().BackKeyNavigatingOffenders.TryGetValue(navMethod.ContainingType, out targets);
+ if (targets == null) {
+ targets = new HashSet<Tuple<IMethodReference, string>>();
+ }
+ string indirectTargeting = "<unknown indirect navigation> via (";
+ foreach (IMethodDefinition methDef in indirects) {
+ indirectTargeting += methDef.ContainingType.ToString() + "." + methDef.Name.Value + ", ";
+ }
+ indirectTargeting += ")";
+ targets.Add(Tuple.Create<IMethodReference, string>(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<ITypeReference,string>(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<string> targets = PhoneCodeHelper.instance().BackKeyNavigatingOffenders[type];
+ ICollection<Tuple<IMethodReference,string>> 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<IMethodReference,string> 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<ITypeReference,string> 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) {