summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BCT/BytecodeTranslator/BytecodeTranslator.csproj1
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneTraverser.cs130
-rw-r--r--BCT/BytecodeTranslator/Program.cs12
-rw-r--r--BCT/BytecodeTranslator/Sink.cs9
-rw-r--r--BCT/PhoneControlsExtractor/PhoneControlsExtractor.py3
-rw-r--r--BCT/TranslationPlugins/PhoneControlsPlugin.cs6
6 files changed, 144 insertions, 17 deletions
diff --git a/BCT/BytecodeTranslator/BytecodeTranslator.csproj b/BCT/BytecodeTranslator/BytecodeTranslator.csproj
index 51729cce..0393913a 100644
--- a/BCT/BytecodeTranslator/BytecodeTranslator.csproj
+++ b/BCT/BytecodeTranslator/BytecodeTranslator.csproj
@@ -125,6 +125,7 @@
<Compile Include="Heap.cs" />
<Compile Include="HeapFactory.cs" />
<Compile Include="MetadataTraverser.cs" />
+ <Compile Include="Phone\PhoneTraverser.cs" />
<Compile Include="Prelude.cs" />
<Compile Include="ExpressionTraverser.cs" />
<Compile Include="Sink.cs" />
diff --git a/BCT/BytecodeTranslator/Phone/PhoneTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneTraverser.cs
new file mode 100644
index 00000000..98aa4461
--- /dev/null
+++ b/BCT/BytecodeTranslator/Phone/PhoneTraverser.cs
@@ -0,0 +1,130 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Cci;
+using Microsoft.Cci.MetadataReader;
+using Microsoft.Cci.MutableCodeModel;
+using Microsoft.Cci.Contracts;
+using Microsoft.Cci.ILToCodeModel;
+
+using Bpl = Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+
+
+namespace BytecodeTranslator {
+
+ /// <summary>
+ /// Traverse code looking for phone specific points of interest, possibly injecting necessary code in-between
+ /// </summary>
+
+ public class PhoneCodeTraverser : BaseCodeTraverser {
+ private readonly IMethodDefinition methodBeingTraversed;
+ private static bool initializationEncountered;
+
+ public PhoneCodeTraverser(IMethodDefinition traversedMethod) : base() {
+ this.methodBeingTraversed = traversedMethod;
+ }
+
+ public void injectPhoneControlsCode(BlockStatement block) {
+ this.Visit(block);
+ }
+
+ private void injectPhoneInitializationCode(IBlockStatement block, IStatement statementAfter) {
+ }
+
+ public override void Visit(IBlockStatement block) {
+ initializationEncountered = false;
+ foreach (IStatement statement in block.Statements) {
+ this.Visit(statement);
+ if (initializationEncountered) {
+ injectPhoneInitializationCode(block, statement);
+ break;
+ }
+ }
+ }
+
+ public override void Visit(IMethodCall methodCall) {
+ if (methodCall.IsStaticCall ||
+ !methodCall.MethodToCall.ContainingType.ResolvedType.Equals(methodBeingTraversed.Container) ||
+ methodCall.MethodToCall.Name.Value != "InitializeComponent" ||
+ methodCall.Arguments.Any())
+ return;
+
+ // otherwise we need to insert the desired code after this call
+ // TODO make sure I am dealing with the MUTABLE code model
+ }
+ }
+
+ /// <summary>
+ /// Traverse metadata looking only for PhoneApplicationPage's constructors
+ /// </summary>
+ public class PhoneMetadataTraverser : BaseMetadataTraverser {
+
+ public PhoneMetadataTraverser()
+ : base() {
+ }
+
+ public override void Visit(IModule module) {
+ base.Visit(module);
+ }
+
+ public override void Visit(IAssembly assembly) {
+ base.Visit(assembly);
+ }
+
+ /// <summary>
+ /// Check if the type being defined is a PhoneApplicationPage, uninteresting otherwise
+ /// </summary>
+ ///
+ public override void Visit(ITypeDefinition typeDefinition) {
+ if (typeDefinition.IsClass && isPhoneApplicationPage(typeDefinition)) {
+ base.Visit(typeDefinition);
+ }
+ }
+
+ private bool isPhoneApplicationPage(ITypeDefinition typeDefinition) {
+ ITypeReference baseClass = typeDefinition.BaseClasses.FirstOrDefault();
+ ITypeDefinition baseClassDef;
+ while (baseClass != null) {
+ baseClassDef = baseClass.ResolvedType;
+ if (baseClassDef is INamespaceTypeDefinition) {
+ if (((INamespaceTypeDefinition) baseClassDef).Name.Value == "PhoneApplicationPage" &&
+ ((INamespaceTypeDefinition) baseClassDef).Container.ToString() == "Microsoft.Phone.Controls") {
+ return true;
+ }
+ }
+ baseClass = baseClass.ResolvedType.BaseClasses.FirstOrDefault();
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Check if it is traversing a constructor. If so, place necessary code after InitializeComponent() call
+ /// </summary>
+ public override void Visit(IMethodDefinition method) {
+ if (!method.IsConstructor)
+ return;
+
+ PhoneCodeTraverser codeTraverser = new PhoneCodeTraverser(method);
+ var methodBody = method.Body as ISourceMethodBody;
+ if (methodBody == null)
+ return;
+ var block = methodBody.Block as BlockStatement;
+ codeTraverser.injectPhoneControlsCode(block);
+ }
+
+ public virtual void InjectPhoneCodeAssemblies(IEnumerable<IUnit> assemblies) {
+ foreach (var a in assemblies) {
+ a.Dispatch(this);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/BCT/BytecodeTranslator/Program.cs b/BCT/BytecodeTranslator/Program.cs
index 05366fc5..7ce0c37a 100644
--- a/BCT/BytecodeTranslator/Program.cs
+++ b/BCT/BytecodeTranslator/Program.cs
@@ -174,18 +174,18 @@ namespace BytecodeTranslator {
var primaryModule = modules[0];
+ if (phoneControlsConfigFile != null && phoneControlsConfigFile != "") {
+ PhoneMetadataTraverser tr = new PhoneMetadataTraverser();
+ tr.InjectPhoneCodeAssemblies(modules);
+ }
+
TraverserFactory traverserFactory;
if (wholeProgram)
traverserFactory = new WholeProgram();
else
traverserFactory = new CLRSemantics();
- Sink sink;
- if (phoneControlsConfigFile != null && phoneControlsConfigFile != "") {
- sink = new Sink(host, traverserFactory, heapFactory, phoneControlsConfigFile);
- } else {
- sink = new Sink(host, traverserFactory, heapFactory);
- }
+ Sink sink= new Sink(host, traverserFactory, heapFactory);
TranslationHelper.tmpVarCounter = 0;
MetadataTraverser translator = traverserFactory.MakeMetadataTraverser(sink, contractExtractors, pdbReaders);
diff --git a/BCT/BytecodeTranslator/Sink.cs b/BCT/BytecodeTranslator/Sink.cs
index f81581c9..b5c01fc1 100644
--- a/BCT/BytecodeTranslator/Sink.cs
+++ b/BCT/BytecodeTranslator/Sink.cs
@@ -22,20 +22,11 @@ namespace BytecodeTranslator {
public class Sink {
- private TranslationPlugins.PhoneControlsPlugin phonePlugin;
-
public TraverserFactory Factory {
get { return this.factory; }
}
readonly TraverserFactory factory;
- public Sink(IContractAwareHost host, TraverserFactory factory, HeapFactory heapFactory, string phoneControlsConfigFile)
- : this(host, factory, heapFactory) {
- // TODO I'm loading the config file here, it would be best to create the sink and then register callback plugins from outside
-
- phonePlugin = new TranslationPlugins.PhoneControlsPlugin(phoneControlsConfigFile);
- }
-
public Sink(IContractAwareHost host, TraverserFactory factory, HeapFactory heapFactory) {
Contract.Requires(host != null);
Contract.Requires(factory != null);
diff --git a/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py
index 46f5aaf7..8ca29036 100644
--- a/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py
+++ b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py
@@ -117,8 +117,7 @@ def outputPhoneControls(outputFileName):
outputFile.close()
def extractPhoneControls(sourceDir):
- fileList= [os.path.normcase(fileName) for fileName in os.listdir(sourceDir)]
- fileList= [os.path.join(sourceDir, fileName) for fileName in fileList if os.path.splitext(fileName)[1] == ".xaml"]
+ fileList= [os.path.join(sourceDir, fileName) for fileName in os.listdir(sourceDir) if os.path.splitext(fileName)[1] == ".xaml"]
for fileName in fileList:
extractPhoneControlsFromPage(fileName)
diff --git a/BCT/TranslationPlugins/PhoneControlsPlugin.cs b/BCT/TranslationPlugins/PhoneControlsPlugin.cs
index d63b6489..9ed1c7df 100644
--- a/BCT/TranslationPlugins/PhoneControlsPlugin.cs
+++ b/BCT/TranslationPlugins/PhoneControlsPlugin.cs
@@ -98,6 +98,11 @@ namespace TranslationPlugins {
private IDictionary<string, PageStructure> pageStructureInfo;
+ public static string getFullyQualifiedControlClass(string controlClass) {
+ // TODO do an actual API discovery. The problem will be differencing 7.0 apps from 7.1 apps
+ return "System.Windows.Controls." + controlClass;
+ }
+
public PhoneControlsPlugin(string configFile) {
pageStructureInfo = new Dictionary<string, PageStructure>();
StreamReader fileStream = null;
@@ -172,6 +177,7 @@ namespace TranslationPlugins {
controlInfoStr.setHandler(Event.Unchecked, uncheckedHandler);
pageStr.setControlInfo(controlName, controlInfoStr);
+ pageStructureInfo[pageClass] = pageStr;
configLine = configStream.ReadLine();
}