summaryrefslogtreecommitdiff
path: root/BCT/BytecodeTranslator
diff options
context:
space:
mode:
Diffstat (limited to 'BCT/BytecodeTranslator')
-rw-r--r--BCT/BytecodeTranslator/BytecodeTranslator.csproj55
-rw-r--r--BCT/BytecodeTranslator/ExpressionTraverser.cs1
-rw-r--r--BCT/BytecodeTranslator/MetadataTraverser.cs27
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneBackKeyCallbackTraverser.cs32
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs62
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs39
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs73
-rw-r--r--BCT/BytecodeTranslator/Program.cs68
-rw-r--r--BCT/BytecodeTranslator/Sink.cs16
9 files changed, 275 insertions, 98 deletions
diff --git a/BCT/BytecodeTranslator/BytecodeTranslator.csproj b/BCT/BytecodeTranslator/BytecodeTranslator.csproj
index d0e4a87e..f64ba3a7 100644
--- a/BCT/BytecodeTranslator/BytecodeTranslator.csproj
+++ b/BCT/BytecodeTranslator/BytecodeTranslator.csproj
@@ -146,45 +146,49 @@
<Content Include="Readme.txt" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Metadata\Sources\MetadataHelper\MetadataHelper.csproj">
+ <ProjectReference Include="..\..\..\CCICodeBox\Converters\ContractExtractor\ContractExtractor.csproj">
+ <Project>{0703D916-A881-45E6-A5CD-6BC50E2E30E2}</Project>
+ <Name>ContractExtractor</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\CCICodeBox\Converters\ILToCodeModel\ILToCodeModel.csproj">
+ <Project>{27F2A417-B6ED-43AD-A38E-A0B6142216F6}</Project>
+ <Name>ILToCodeModel</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\CCICodeBox\CoreObjectModel\CodeModel\CodeModel.csproj">
+ <Project>{035FEA7F-0D36-4AE4-B694-EC45191B9AF2}</Project>
+ <Name>CodeModel</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\CCICodeBox\CoreObjectModel\MetadataHelper\MetadataHelper.csproj">
<Project>{4A34A3C5-6176-49D7-A4C5-B2B671247F8F}</Project>
<Name>MetadataHelper</Name>
</ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Metadata\Sources\MetadataModel\MetadataModel.csproj">
+ <ProjectReference Include="..\..\..\CCICodeBox\CoreObjectModel\MetadataModel\MetadataModel.csproj">
<Project>{33CAB640-0D03-43DF-81BD-22CDC6C0A597}</Project>
<Name>MetadataModel</Name>
</ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Metadata\Sources\MutableMetadataModel\MutableMetadataModel.csproj">
+ <ProjectReference Include="..\..\..\CCICodeBox\CoreObjectModel\MutableCodeModel\MutableCodeModel.csproj">
+ <Project>{319E150C-8F33-49E7-81CA-30F02F9BA90A}</Project>
+ <Name>MutableCodeModel</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\CCICodeBox\CoreObjectModel\MutableMetadataModel\MutableMetadataModel.csproj">
<Project>{319E151C-8F33-49E7-81C9-30F02F9BA90A}</Project>
<Name>MutableMetadataModel</Name>
</ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Metadata\Sources\PdbReader\PdbReader.csproj">
+ <ProjectReference Include="..\..\..\CCICodeBox\CoreObjectModel\SourceModel\SourceModel.csproj">
+ <Project>{4B0054FD-124A-4037-9965-BDB55E6BF389}</Project>
+ <Name>SourceModel</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\CCICodeBox\PDBReaderAndWriter\PdbReader\PdbReader.csproj">
<Project>{A6A31B03-7C3D-4DE6-AA73-BE88116BC40A}</Project>
<Name>PdbReader</Name>
</ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Metadata\Sources\PeReader\PeReader.csproj">
+ <ProjectReference Include="..\..\..\CCICodeBox\PEReaderAndWriter\PEReader\PeReader.csproj">
<Project>{34B9A0CE-DF18-4CBC-8F7A-90C2B74338D5}</Project>
<Name>PeReader</Name>
</ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Metadata\Sources\SourceModel\SourceModel.csproj">
- <Project>{4B0054FD-124A-4037-9965-BDB55E6BF389}</Project>
- <Name>SourceModel</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Sources\CodeModel\CodeModel.csproj">
- <Project>{035FEA7F-0D36-4AE4-B694-EC45191B9AF2}</Project>
- <Name>CodeModel</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Sources\ContractExtractor\ContractExtractor.csproj">
- <Project>{0703D916-A881-45E6-A5CD-6BC50E2E30E2}</Project>
- <Name>ContractExtractor</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Sources\ILToCodeModel\ILToCodeModel.csproj">
- <Project>{27F2A417-B6ED-43AD-A38E-A0B6142216F6}</Project>
- <Name>ILToCodeModel</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\..\CCICodePlex\Ast\Sources\MutableCodeModel\MutableCodeModel.csproj">
- <Project>{319E150C-8F33-49E7-81CA-30F02F9BA90A}</Project>
- <Name>MutableCodeModel</Name>
+ <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>
@@ -214,6 +218,9 @@
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
+ <ItemGroup>
+ <WCFMetadata Include="Service References\" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/BCT/BytecodeTranslator/ExpressionTraverser.cs b/BCT/BytecodeTranslator/ExpressionTraverser.cs
index 2dd57d27..6498edb9 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/MetadataTraverser.cs b/BCT/BytecodeTranslator/MetadataTraverser.cs
index d5e19fb0..f1f7e714 100644
--- a/BCT/BytecodeTranslator/MetadataTraverser.cs
+++ b/BCT/BytecodeTranslator/MetadataTraverser.cs
@@ -70,7 +70,7 @@ namespace BytecodeTranslator {
var savedPrivateTypes = this.privateTypes;
this.privateTypes = new List<ITypeDefinition>();
- trackPageNameVariableName(typeDefinition);
+ trackPhonePageNameVariableName(typeDefinition);
trackPhoneApplicationClassname(typeDefinition);
if (typeDefinition.IsClass) {
@@ -117,7 +117,7 @@ namespace BytecodeTranslator {
}
}
- private void trackPageNameVariableName(ITypeDefinition typeDef) {
+ private void trackPhonePageNameVariableName(ITypeDefinition typeDef) {
if (PhoneCodeHelper.instance().PhonePlugin != null && typeDef.isPhoneApplicationPageClass(sink.host)) {
INamespaceTypeDefinition namedTypeDef = typeDef as INamespaceTypeDefinition;
string fullyQualifiedName = namedTypeDef.ToString();
@@ -130,6 +130,29 @@ namespace BytecodeTranslator {
}
}
+ /*
+ private void translateAnonymousControlsForPage(ITypeDefinition typeDef) {
+ if (PhoneCodeHelper.instance().PhonePlugin != null && typeDef.isPhoneApplicationPageClass(sink.host)) {
+ IEnumerable<ControlInfoStructure> pageCtrls= PhoneCodeHelper.instance().PhonePlugin.getControlsForPage(typeDef.ToString());
+ foreach (ControlInfoStructure ctrlInfo in pageCtrls) {
+ if (ctrlInfo.Name.Contains(PhoneControlsPlugin.BOOGIE_DUMMY_CONTROL)) {
+ string anonymousControlName = ctrlInfo.Name;
+ IFieldDefinition fieldDef = new FieldDefinition() {
+ ContainingTypeDefinition = typeDef,
+ Name = sink.host.NameTable.GetNameFor(anonymousControlName),
+ InternFactory = sink.host.InternFactory,
+ Visibility = TypeMemberVisibility.Public,
+ Type = sink.host.PlatformType.SystemObject,
+ IsStatic = false,
+ };
+ (typeDef as Microsoft.Cci.MutableCodeModel.NamespaceTypeDefinition).Fields.Add(fieldDef);
+ //sink.FindOrCreateFieldVariable(fieldDef);
+ }
+ }
+ }
+ }
+ * */
+
private void CreateDefaultStructConstructor(ITypeDefinition typeDefinition) {
Contract.Requires(typeDefinition.IsStruct);
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/PhoneInitializationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs
index d79d2c00..d809b752 100644
--- a/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs
+++ b/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs
@@ -102,17 +102,38 @@ namespace BytecodeTranslator.Phone {
phoneAssembly = host.FindAssembly(MSPhoneAssemblyId);
phoneSystemWindowsAssembly = host.FindAssembly(MSPhoneSystemWindowsAssemblyId);
MSPhoneControlsAssembly= host.FindAssembly(MSPhoneControlsAssemblyId);
+ // TODO BUG / XAML DEPENDENCE If a control is declared in XAML, it may be one from a library *not* linked! So, assemblies could be dummy here
// TODO determine the needed types dynamically
- appBarIconButtonType= platform.CreateReference(phoneAssembly, "Microsoft", "Phone", "Shell", "ApplicationBarIconButton");
- checkBoxType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "CheckBox");
- radioButtonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "RadioButton");
- buttonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Button");
- buttonBaseType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Primitives", "ButtonBase");
- toggleButtonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Primitives", "ToggleButton");
- controlType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Control");
- uiElementType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "UIElement");
- pivotType = platform.CreateReference(MSPhoneControlsAssembly, "Microsoft", "Phone", "Controls", "Pivot");
+ if (phoneAssembly != Dummy.Assembly) {
+ appBarIconButtonType = platform.CreateReference(phoneAssembly, "Microsoft", "Phone", "Shell", "ApplicationBarIconButton");
+ } else {
+ appBarIconButtonType = host.PlatformType.SystemObject;
+ }
+
+ if (phoneSystemWindowsAssembly != Dummy.Assembly) {
+ checkBoxType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "CheckBox");
+ radioButtonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "RadioButton");
+ buttonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Button");
+ buttonBaseType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Primitives", "ButtonBase");
+ toggleButtonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Primitives", "ToggleButton");
+ controlType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Control");
+ uiElementType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "UIElement");
+ } else {
+ checkBoxType = host.PlatformType.SystemObject;
+ radioButtonType = host.PlatformType.SystemObject;
+ buttonType = host.PlatformType.SystemObject;
+ buttonBaseType = host.PlatformType.SystemObject;
+ toggleButtonType = host.PlatformType.SystemObject;
+ controlType = host.PlatformType.SystemObject;
+ uiElementType = host.PlatformType.SystemObject;
+ }
+
+ if (MSPhoneControlsAssembly != Dummy.Assembly) {
+ pivotType = platform.CreateReference(MSPhoneControlsAssembly, "Microsoft", "Phone", "Controls", "Pivot");
+ } else {
+ pivotType = host.PlatformType.SystemObject;
+ }
trueConstant = new CompileTimeConstant() {
Type = platform.SystemBoolean,
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 a848c3cf..5123da92 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) {
diff --git a/BCT/BytecodeTranslator/Sink.cs b/BCT/BytecodeTranslator/Sink.cs
index c6464536..ea0b22c9 100644
--- a/BCT/BytecodeTranslator/Sink.cs
+++ b/BCT/BytecodeTranslator/Sink.cs
@@ -243,6 +243,14 @@ namespace BytecodeTranslator {
var key = field.InternedKey;
if (!this.declaredFields.TryGetValue(key, out v)) {
v = this.Heap.CreateFieldVariable(field);
+
+ var isExtern = this.assemblyBeingTranslated != null &&
+ !TypeHelper.GetDefiningUnitReference(field.ContainingType).UnitIdentity.Equals(this.assemblyBeingTranslated.UnitIdentity);
+ if (isExtern) {
+ var attrib = new Bpl.QKeyValue(Bpl.Token.NoToken, "extern", new List<object>(1), null);
+ v.Attributes = attrib;
+ }
+
this.declaredFields.Add(key, v);
this.TranslatedProgram.TopLevelDeclarations.Add(v);
}
@@ -270,6 +278,14 @@ namespace BytecodeTranslator {
if (v == null) {
v = this.Heap.CreateEventVariable(e);
+
+ var isExtern = this.assemblyBeingTranslated != null &&
+ !TypeHelper.GetDefiningUnitReference(e.ContainingType).UnitIdentity.Equals(this.assemblyBeingTranslated.UnitIdentity);
+ if (isExtern) {
+ var attrib = new Bpl.QKeyValue(Bpl.Token.NoToken, "extern", new List<object>(1), null);
+ v.Attributes = attrib;
+ }
+
this.TranslatedProgram.TopLevelDeclarations.Add(v);
}
this.declaredEvents.Add(e, v);