From 8b3b8b1f511c6230d54daab12ae5f068c9595869 Mon Sep 17 00:00:00 2001 From: t-espave Date: Wed, 3 Aug 2011 10:49:21 -0700 Subject: (phone bct) user feedback, showing possibly anomalous nav targets (bct) '+' invalid in string literals --- BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs | 8 +++++--- BCT/BytecodeTranslator/TranslationHelper.cs | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'BCT') diff --git a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs index f94f0044..f32e7f95 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs @@ -140,11 +140,13 @@ namespace BytecodeTranslator.Phone { string target; if (isNavigationOnBackKeyPressHandler(methodCall, out target)) { PhoneCodeHelper.instance().BackKeyPressNavigates = true; - ICollection targets = PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed]; - if (targets == null) { + ICollection targets; + try { + targets= PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed]; + } catch (KeyNotFoundException) { targets = new HashSet(); } - targets.Add(target); + targets.Add("\"" + target + "\""); PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed]= targets; } else if (isCancelOnBackKeyPressHandler(methodCall)) { PhoneCodeHelper.instance().BackKeyPressHandlerCancels = true; diff --git a/BCT/BytecodeTranslator/TranslationHelper.cs b/BCT/BytecodeTranslator/TranslationHelper.cs index ad264c48..e91af9c2 100644 --- a/BCT/BytecodeTranslator/TranslationHelper.cs +++ b/BCT/BytecodeTranslator/TranslationHelper.cs @@ -153,6 +153,7 @@ namespace BytecodeTranslator { s = s.Replace('[', '$'); s = s.Replace(']', '$'); s = s.Replace('|', '$'); + s = s.Replace('+', '$'); s = GetRidOfSurrogateCharacters(s); return s; } -- cgit v1.2.3 From 026cd487e878ab5fa703010a79b18491683205d8 Mon Sep 17 00:00:00 2001 From: t-espave Date: Wed, 3 Aug 2011 16:52:20 -0700 Subject: (phone bct) moved some code to urihelper --- BCT/BytecodeTranslator/MetadataTraverser.cs | 2 +- BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs | 24 +++++++++++++++++++++- .../Phone/PhoneNavigationTraverser.cs | 6 ++++-- BCT/TranslationPlugins/PhoneControlsPlugin.cs | 22 -------------------- 4 files changed, 28 insertions(+), 26 deletions(-) (limited to 'BCT') diff --git a/BCT/BytecodeTranslator/MetadataTraverser.cs b/BCT/BytecodeTranslator/MetadataTraverser.cs index f6903b8a..daf64eac 100644 --- a/BCT/BytecodeTranslator/MetadataTraverser.cs +++ b/BCT/BytecodeTranslator/MetadataTraverser.cs @@ -122,7 +122,7 @@ namespace BytecodeTranslator { string fullyQualifiedName = namedTypeDef.ToString(); string xamlForClass = PhoneCodeHelper.instance().getXAMLForPage(fullyQualifiedName); if (xamlForClass != null) { // if not it is possibly an abstract page - string uriName = PhoneControlsPlugin.getURIBase(xamlForClass); + string uriName = UriHelper.getURIBase(xamlForClass); Bpl.Constant uriConstant = sink.FindOrCreateConstant(uriName); PhoneCodeHelper.instance().setBoogieStringPageNameForPageClass(fullyQualifiedName, uriConstant.Name); } diff --git a/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs b/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs index 6be74264..cd71e7cc 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs @@ -9,6 +9,28 @@ using Microsoft.Cci.MutableCodeModel; namespace BytecodeTranslator.Phone { public static class UriHelper { + /// + /// uri is a valid URI but possibly partial (incomplete ?arg= values) and overspecified (complete ?arg=values) + /// This method returns a base URI + /// + /// + /// + public static string getURIBase(string uri) { + // I need to build an absolute URI just to call getComponents() ... + Uri mockBaseUri = new Uri("mock://mock/", UriKind.RelativeOrAbsolute); + Uri realUri; + try { + realUri = new Uri(uri, UriKind.Absolute); + } catch (UriFormatException) { + // uri string is relative + realUri = new Uri(mockBaseUri, uri); + } + + string str = realUri.GetComponents(UriComponents.Path | UriComponents.StrongAuthority | UriComponents.Scheme, UriFormat.UriEscaped); + Uri mockStrippedUri = new Uri(str); + return mockBaseUri.MakeRelativeUri(mockStrippedUri).ToString(); + } + /// /// checks if argument is locally created URI with static URI target /// @@ -32,7 +54,7 @@ namespace BytecodeTranslator.Phone { if (staticURITarget == null) return false; - uri = staticURITarget.Value as string; + uri= staticURITarget.Value as string; return true; } diff --git a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs index f32e7f95..59c35b3b 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs @@ -41,7 +41,7 @@ namespace BytecodeTranslator.Phone { Assignment uriInitAssign = new Assignment() { Source = new CompileTimeConstant() { Type = host.PlatformType.SystemString, - Value = PhoneControlsPlugin.getURIBase(mainPageUri), + Value = UriHelper.getURIBase(mainPageUri), }, Type = host.PlatformType.SystemString, Target = new TargetExpression() { @@ -106,6 +106,8 @@ namespace BytecodeTranslator.Phone { UriHelper.isArgumentURILocallyCreatedStaticRoot(expr, host, out target); if (!isStatic) target = "--Other non inferrable target--"; + else + target = UriHelper.getURIBase(target); } catch (InvalidOperationException) { } } @@ -249,7 +251,7 @@ namespace BytecodeTranslator.Phone { Assignment currentURIAssign = new Assignment() { Source = new CompileTimeConstant() { Type = host.PlatformType.SystemString, - Value = PhoneControlsPlugin.getURIBase(entry.Item3), + Value = UriHelper.getURIBase(entry.Item3), }, Type = host.PlatformType.SystemString, Target = new TargetExpression() { diff --git a/BCT/TranslationPlugins/PhoneControlsPlugin.cs b/BCT/TranslationPlugins/PhoneControlsPlugin.cs index e539b1b8..41eeaebb 100644 --- a/BCT/TranslationPlugins/PhoneControlsPlugin.cs +++ b/BCT/TranslationPlugins/PhoneControlsPlugin.cs @@ -125,28 +125,6 @@ namespace TranslationPlugins { return mockBaseUri.MakeRelativeUri(mockStrippedUri).ToString(); } - /// - /// uri is a valid URI but possibly partial (incomplete ?arg= values) and overspecified (complete ?arg=values) - /// This method returns a base URI - /// - /// - /// - public static string getURIBase(string uri) { - // I need to build an absolute URI just to call getComponents() ... - Uri mockBaseUri = new Uri("mock://mock/", UriKind.RelativeOrAbsolute); - Uri realUri; - try { - realUri = new Uri(uri, UriKind.Absolute); - } catch (UriFormatException) { - // uri string is relative - realUri = new Uri(mockBaseUri, uri); - } - - string str = realUri.GetComponents(UriComponents.Path | UriComponents.StrongAuthority | UriComponents.Scheme, UriFormat.UriEscaped); - Uri mockStrippedUri = new Uri(str); - return mockBaseUri.MakeRelativeUri(mockStrippedUri).ToString(); - } - //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; -- cgit v1.2.3 From 8bf4c4336978eb2cef75a84eab4d33ba05234ebf Mon Sep 17 00:00:00 2001 From: t-espave Date: Thu, 4 Aug 2011 09:10:56 -0700 Subject: (phone bct) monitoring pivot controls --- .../PhoneBoogieCodeGenerator.py | 15 ++++++++----- .../PhoneControlsExtractor.py | 12 +++++++--- BCT/TranslationPlugins/PhoneControlsPlugin.cs | 26 +++++++++++++++++----- 3 files changed, 39 insertions(+), 14 deletions(-) (limited to 'BCT') diff --git a/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py b/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py index 37b35746..101fb51c 100644 --- a/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py +++ b/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py @@ -5,7 +5,7 @@ from xml.dom import minidom from itertools import product import xml.dom -CONTROL_NAMES= ["Button", "CheckBox", "RadioButton"] +CONTROL_NAMES= ["Button", "CheckBox", "RadioButton", "ApplicationBarIconButton", "Pivot"] CONTAINER_CONTROL_NAMES= ["Canvas", "Grid", "StackPanel"] # TODO externalize strings, share with C# code @@ -29,7 +29,7 @@ def showUsage(): print "\t--controls : Phone app control info. See PhoneControlsExtractor. Short form: -c" print "\t--output : file to write with boilerplate code. Short form: -o\n" -def loadControlInfo(infoMap, controlClass, controlName, enabled, visible, clickHandler, checkedHandler, uncheckedHandler, bplName): +def loadControlInfo(infoMap, controlClass, controlName, enabled, visible, clickHandler, checkedHandler, uncheckedHandler, selectionChangedHandler, bplName): newControl={} newControl["class"]= controlClass newControl["enabled"]= enabled @@ -37,6 +37,7 @@ def loadControlInfo(infoMap, controlClass, controlName, enabled, visible, clickH newControl["clickHandler"]= clickHandler newControl["checkedHandler"]= checkedHandler newControl["uncheckedHandler"]= uncheckedHandler + newControl["selectionChangedHandler"]= selectionChangedHandler newControl["bplName"]=bplName infoMap[controlName]= newControl @@ -139,6 +140,10 @@ def outputPageControlDriver(file, originalPageName, boogiePageName): file.write("\t\t\t\tif ($handlerToActivate == 2) {\n") file.write("\t\t\t\t\tcall " + staticControlsMap[originalPageName]["class"] + "." + controlInfo["uncheckedHandler"] + "$System.Object$System.Windows.RoutedEventArgs(" + controlInfo["bplName"] + "[" + boogiePageName + "],null,null);\n") file.write("\t\t\t\t}\n") + if not controlInfo["selectionChangedHandler"] == "": + file.write("\t\t\t\tif ($handlerToActivate == 3) {\n") + file.write("\t\t\t\t\tcall " + staticControlsMap[originalPageName]["class"] + "." + controlInfo["selectionChangedHandler"] + "$System.Object$System.Windows.RoutedEventArgs(" + controlInfo["bplName"] + "[" + boogiePageName + "],null,null);\n") + file.write("\t\t\t\t}\n") file.write("\t\t\t}\n") file.write("\t\t}\n") @@ -203,14 +208,14 @@ def buildControlInfo(controlInfoFileName): file = open(controlInfoFileName, "r") # Info file format is first line containing only the main page, another line with boogie's current navigation variable and then one line per - # ,,,,,,,,,, + # ,,,,,,,,,,, mainPageXAML= file.readline().strip() currentNavigationVariable= file.readline().strip() mainAppClassname= file.readline().strip() infoLine= file.readline().strip() while not infoLine == "": - pageClass, pageName, pageBoogieStringName, controlClass, controlName, enabled, visible, clickHandler, checkedHandler, uncheckedHandler, bplName= infoLine.split(",") + pageClass, pageName, pageBoogieStringName, controlClass, controlName, enabled, visible, clickHandler, checkedHandler, uncheckedHandler, selectionChangedHandler, bplName= infoLine.split(",") pageInfo={} pageInfo["class"]=pageClass try: @@ -224,7 +229,7 @@ def buildControlInfo(controlInfoFileName): pageControlInfo= pageInfo["controls"] except KeyError: pageInfo["controls"]=pageControlInfo - loadControlInfo(pageControlInfo, controlClass, controlName, enabled, visible, clickHandler, checkedHandler, uncheckedHandler, bplName) + loadControlInfo(pageControlInfo, controlClass, controlName, enabled, visible, clickHandler, checkedHandler, uncheckedHandler, selectionChangedHandler, bplName) pageInfo["controls"]= pageControlInfo staticControlsMap[pageName]=pageInfo diff --git a/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py index 9285d6c8..27517d0d 100644 --- a/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py +++ b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py @@ -4,7 +4,7 @@ import os from xml.dom import minidom import xml.dom -CONTROL_NAMES= ["Button", "CheckBox", "RadioButton", "ApplicationBarIconButton"] +CONTROL_NAMES= ["Button", "CheckBox", "RadioButton", "ApplicationBarIconButton", "Pivot"] # TODO maybe a control is enabled but its parent is not, must take this into account # TODO a possible solution is to tie the enabled value to that of the parent in the app until it is either overriden @@ -70,6 +70,7 @@ def addDummyControlToMap(pageXAML, parentPage): newControl["Click"] = "" newControl["Checked"] = "" newControl["Unchecked"] = "" + newControl["SelectionChanged"]= "" newControl["XAML"]= pageXAML pageControls.append(newControl) staticControlsMap[parentPage]= pageControls @@ -98,6 +99,7 @@ def addControlToMap(pageXAML, parentPage, controlNode): newControl["Click"] = controlNode.getAttribute("Click").replace(",",COMMA_REPLACEMENT).replace("=",COMMA_REPLACEMENT) newControl["Checked"] = controlNode.getAttribute("Checked").replace(",",COMMA_REPLACEMENT).replace("=",COMMA_REPLACEMENT) newControl["Unchecked"] = controlNode.getAttribute("Unchecked").replace(",",COMMA_REPLACEMENT).replace("=",COMMA_REPLACEMENT) + newControl["SelectionChanged"] = controlNode.getAttribute("SelectionChanged").replace(",",COMMA_REPLACEMENT).replace("=",COMMA_REPLACEMENT) newControl["XAML"]= pageXAML pageControls.append(newControl) staticControlsMap[parentPage]= pageControls @@ -145,7 +147,7 @@ def outputPhoneControls(outputFileName): outputFile= open(outputFileName, "w") # Output format is first line containing only the main page, then line containing boogie navigation variable, and then one line per - # ,,,,,,,,, + # ,,,,,,,,,, outputFile.write(mainPageXAML + "\n") outputFile.write("dummyNavigationVariable_unknown\n") outputFile.write("dummyMainAppName_unknown\n") # I could possibly deduce it from WMAppManifest.xml, but I'm unsure. Doing it later is safe anyway @@ -167,10 +169,14 @@ def outputPhoneControls(outputFileName): unchecked= control["Unchecked"] if (unchecked.find(COMMA_REPLACEMENT) != -1): unchecked= "" + selectionChanged= control["Unchecked"] + if (selectionChanged.find(COMMA_REPLACEMENT) != -1): + selectionChanged= "" pageXAML= control["XAML"] # last comma is to account for bpl translation name, that is unknown for now # boogie string page name is unknown for now - outputFile.write(page + "," + os.path.basename(pageXAML) + ",dummyBoogieStringPageName," + control["Type"] + "," + control["Name"] + "," + isEnabled + "," + visibility + "," + click + "," + checked + "," + unchecked + ",\n") + outputFile.write(page + "," + os.path.basename(pageXAML) + ",dummyBoogieStringPageName," + control["Type"] + "," + control["Name"] + \ + "," + isEnabled + "," + visibility + "," + click + "," + checked + "," + unchecked + "," + selectionChanged + ",\n") outputFile.close() diff --git a/BCT/TranslationPlugins/PhoneControlsPlugin.cs b/BCT/TranslationPlugins/PhoneControlsPlugin.cs index 41eeaebb..168ba088 100644 --- a/BCT/TranslationPlugins/PhoneControlsPlugin.cs +++ b/BCT/TranslationPlugins/PhoneControlsPlugin.cs @@ -7,7 +7,7 @@ using System.IO; namespace TranslationPlugins { public enum Visibility { Visible, Collapsed }; - public enum Event { Click, Checked, Unchecked }; + public enum Event { Click, Checked, Unchecked, SelectionChanged }; public class HandlerSignature { public static string[] getParameterTypesForHandler(Event controlEvent) { @@ -94,7 +94,7 @@ namespace TranslationPlugins { public class PhoneControlsPlugin : TranslationPlugin { // TODO this will probably need a complete rewrite once it is event based, and make it more push than pull // TODO but it doesn't make sense right now to make it BCT or CCI aware - private static int CONFIG_LINE_FIELDS= 11; + private static int CONFIG_LINE_FIELDS= 12; private static int PAGE_CLASS_FIELD= 0; private static int PAGE_XAML_FIELD= 1; private static int PAGE_BOOGIE_STRING_FIELD = 2; @@ -105,7 +105,8 @@ namespace TranslationPlugins { private static int CLICK_HANDLER_FIELD= 7; private static int CHECKED_HANDLER_FIELD= 8; private static int UNCHECKED_HANDLER_FIELD = 9; - private static int BPL_NAME_FIELD = 10; + private static int SELECTIONCHANGED_HANDLER_FIELD = 10; + private static int BPL_NAME_FIELD = 11; private IDictionary pageStructureInfo; @@ -190,7 +191,8 @@ namespace TranslationPlugins { public void DumpControlStructure(StreamWriter outputStream) { // maintain same format as input format - string pageClass, pageXAML, pageBoogieStringName, controlClass, controlName, enabled, visibility, clickHandler, checkedHandler, uncheckedHandler, bplName; + string pageClass, pageXAML, pageBoogieStringName, controlClass, controlName, enabled, visibility, clickHandler, + checkedHandler, uncheckedHandler, selectionChangedHandler, bplName; outputStream.WriteLine(getMainPageXAML()); outputStream.WriteLine(getBoogieNavigationVariable()); outputStream.WriteLine(getMainAppTypeName()); @@ -231,8 +233,17 @@ namespace TranslationPlugins { } else { uncheckedHandler = ""; } + + handlers = controlInfo.getHandlers(Event.SelectionChanged); + if (handlers.Any()) { + selectionChangedHandler= handlers.First().Name; + } else { + selectionChangedHandler = ""; + } bplName = controlInfo.BplName; - outputStream.WriteLine(pageClass + "," + pageXAML + "," + pageBoogieStringName + "," + controlClass + "," + controlName + "," + enabled + "," + visibility + "," + clickHandler + "," + checkedHandler + "," + uncheckedHandler + "," + bplName); + outputStream.WriteLine(pageClass + "," + pageXAML + "," + pageBoogieStringName + "," + controlClass + "," + controlName + "," + enabled + "," + + visibility + "," + clickHandler + "," + checkedHandler + "," + uncheckedHandler + "," + selectionChangedHandler + "," + + bplName); } } } @@ -254,7 +265,8 @@ namespace TranslationPlugins { // TODO the page.xaml value is saved with no directory information: if two pages exist with same name but different directories it will treat them as the same // TODO I'm not handling this for now, and I won't be handling relative/absolute URI either for now - string pageClass, pageXAML, pageBoogieStringName, controlClass, controlName, enabled, visibility, clickHandler, checkedHandler, uncheckedHandler, bplName; + string pageClass, pageXAML, pageBoogieStringName, controlClass, controlName, enabled, visibility, clickHandler, checkedHandler, + uncheckedHandler, selectionChangedHandler, bplName; string configLine = configStream.ReadLine(); string[] inputLine; PageStructure pageStr; @@ -295,6 +307,7 @@ namespace TranslationPlugins { clickHandler = inputLine[CLICK_HANDLER_FIELD].Trim(); checkedHandler = inputLine[CHECKED_HANDLER_FIELD].Trim(); uncheckedHandler = inputLine[UNCHECKED_HANDLER_FIELD].Trim(); + selectionChangedHandler = inputLine[SELECTIONCHANGED_HANDLER_FIELD].Trim(); bplName = inputLine[BPL_NAME_FIELD].Trim(); try { @@ -319,6 +332,7 @@ namespace TranslationPlugins { controlInfoStr.setHandler(Event.Click, clickHandler); controlInfoStr.setHandler(Event.Checked, checkedHandler); controlInfoStr.setHandler(Event.Unchecked, uncheckedHandler); + controlInfoStr.setHandler(Event.SelectionChanged, selectionChangedHandler); pageStr.setControlInfo(controlName, controlInfoStr); pageStructureInfo[pageClass] = pageStr; -- cgit v1.2.3 From 7a76fcefe0e0ac2129b5761e74772eda644fc2e9 Mon Sep 17 00:00:00 2001 From: t-espave Date: Thu, 4 Aug 2011 14:56:41 -0700 Subject: (phone bct) anonymous control support boogie nav graph modular analysis code default uris to lowercase to make life easier --- .../Phone/PhoneInitializationTraverser.cs | 10 ++++++++++ .../Phone/PhoneNavigationTraverser.cs | 22 +++++++++++++++------- BCT/BytecodeTranslator/Program.cs | 7 +++++++ .../PhoneBoogieCodeGenerator.py | 15 ++++++++++++++- .../PhoneControlsExtractor.py | 2 +- BCT/TranslationPlugins/PhoneControlsPlugin.cs | 10 ++++++---- 6 files changed, 53 insertions(+), 13 deletions(-) (limited to 'BCT') diff --git a/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs index 4d1f60fb..d79d2c00 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs @@ -31,6 +31,7 @@ namespace BytecodeTranslator.Phone { private IAssemblyReference coreAssemblyRef; private IAssemblyReference phoneAssembly; private IAssemblyReference phoneSystemWindowsAssembly; + private IAssemblyReference MSPhoneControlsAssembly; private INamespaceTypeReference appBarIconButtonType; private INamespaceTypeReference checkBoxType; private INamespaceTypeReference radioButtonType; @@ -39,6 +40,7 @@ namespace BytecodeTranslator.Phone { private INamespaceTypeReference toggleButtonType; private INamespaceTypeReference controlType; private INamespaceTypeReference uiElementType; + private INamespaceTypeReference pivotType; private CompileTimeConstant trueConstant; private CompileTimeConstant falseConstant; @@ -65,6 +67,8 @@ namespace BytecodeTranslator.Phone { return checkBoxType; } else if (classname == "ApplicationBarIconButton") { return appBarIconButtonType; + } else if (classname == "Pivot") { + return pivotType; } else if (classname == "DummyType") { return Dummy.Type; } else { @@ -87,12 +91,17 @@ namespace BytecodeTranslator.Phone { AssemblyIdentity MSPhoneAssemblyId = new AssemblyIdentity(host.NameTable.GetNameFor("Microsoft.Phone"), "", new Version("7.0.0.0"), new byte[] { 0x24, 0xEE, 0xC0, 0xD8, 0xC8, 0x6C, 0xDA, 0x1E }, ""); + AssemblyIdentity MSPhoneControlsAssemblyId= + new AssemblyIdentity(host.NameTable.GetNameFor("Microsoft.Phone.Controls"), "", new Version("7.0.0.0"), + new byte[] { 0x24, 0xEE, 0xC0, 0xD8, 0xC8, 0x6C, 0xDA, 0x1E }, ""); + AssemblyIdentity MSPhoneSystemWindowsAssemblyId = new AssemblyIdentity(host.NameTable.GetNameFor("System.Windows"), coreAssemblyRef.Culture, coreAssemblyRef.Version, coreAssemblyRef.PublicKeyToken, ""); phoneAssembly = host.FindAssembly(MSPhoneAssemblyId); phoneSystemWindowsAssembly = host.FindAssembly(MSPhoneSystemWindowsAssemblyId); + MSPhoneControlsAssembly= host.FindAssembly(MSPhoneControlsAssemblyId); // TODO determine the needed types dynamically appBarIconButtonType= platform.CreateReference(phoneAssembly, "Microsoft", "Phone", "Shell", "ApplicationBarIconButton"); @@ -103,6 +112,7 @@ namespace BytecodeTranslator.Phone { 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"); trueConstant = new CompileTimeConstant() { Type = platform.SystemBoolean, diff --git a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs index 59c35b3b..2d3533aa 100644 --- a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs +++ b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs @@ -13,6 +13,8 @@ namespace BytecodeTranslator.Phone { private ITypeReference cancelEventArgsType; private ITypeReference typeTraversed; private IMethodDefinition methodTraversed; + private static HashSet navCallers= new HashSet(); + public static IEnumerable NavCallers { get { return navCallers; } } public PhoneNavigationCodeTraverser(MetadataReaderHost host, ITypeReference typeTraversed, IMethodDefinition methodTraversed) : base() { this.host = host; @@ -29,10 +31,13 @@ namespace BytecodeTranslator.Phone { cancelEventArgsType = platform.CreateReference(assembly, "System", "ComponentModel", "CancelEventArgs"); } + public override void Visit(IEnumerable assemblyReferences) { + base.Visit(assemblyReferences); + } + + public override void Visit(IMethodDefinition method) { if (method.IsConstructor && PhoneTypeHelper.isPhoneApplicationClass(typeTraversed, host)) { - // TODO BUG doing this is generating a fresh variable definition somewhere that the BCT then translates into two different (identical) declarations - // TODO maybe a bug introduced here or a BCT bug string mainPageUri = PhoneCodeHelper.instance().PhonePlugin.getMainPageXAML(); SourceMethodBody sourceBody = method.Body as SourceMethodBody; if (sourceBody != null) { @@ -78,10 +83,13 @@ namespace BytecodeTranslator.Phone { navCallFound = false; navCallIsStatic = false; this.Visit(statement); - if (navCallFound && navCallIsStatic) { - staticNavStmts.Add(new Tuple(statement, currentStaticMode, unpurifiedFoundURI)); - } else if (navCallFound) { - nonStaticNavStmts.Add(statement); + if (navCallFound) { + navCallers.Add(methodTraversed); + if (navCallIsStatic) { + staticNavStmts.Add(new Tuple(statement, currentStaticMode, unpurifiedFoundURI)); + } else { + nonStaticNavStmts.Add(statement); + } } } @@ -251,7 +259,7 @@ namespace BytecodeTranslator.Phone { Assignment currentURIAssign = new Assignment() { Source = new CompileTimeConstant() { Type = host.PlatformType.SystemString, - Value = UriHelper.getURIBase(entry.Item3), + Value = UriHelper.getURIBase(entry.Item3).ToLower(), }, Type = host.PlatformType.SystemString, Target = new TargetExpression() { diff --git a/BCT/BytecodeTranslator/Program.cs b/BCT/BytecodeTranslator/Program.cs index 18d735af..b3f176f8 100644 --- a/BCT/BytecodeTranslator/Program.cs +++ b/BCT/BytecodeTranslator/Program.cs @@ -324,6 +324,13 @@ namespace BytecodeTranslator { System.Console.WriteLine("Total methods seen: {0}, inlined: {1}", inlineTraverser.TotalMethodsCount, inlineTraverser.InlinedMethodsCount); } + if (PhoneCodeHelper.instance().PhoneNavigationToggled) { + // TODO integrate into the pipeline and spit out the boogie code + foreach (IMethodDefinition def in PhoneNavigationCodeTraverser.NavCallers) { + System.Console.WriteLine(def.ToString()); + } + } + Microsoft.Boogie.TokenTextWriter writer = new Microsoft.Boogie.TokenTextWriter(primaryModule.Name + ".bpl"); Prelude.Emit(writer); sink.TranslatedProgram.Emit(writer); diff --git a/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py b/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py index 101fb51c..2071ce21 100644 --- a/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py +++ b/BCT/PhoneControlsExtractor/PhoneBoogieCodeGenerator.py @@ -20,6 +20,8 @@ originalPageVars= [] boogiePageVars= [] boogiePageClasses= [] dummyPageVar= "dummyBoogieStringPageName" +anonymousControlCount= 0; +ANONYMOUS_CONTROL_PREFIX= "__BOOGIE_ANONYMOUS_CONTROL_" def showUsage(): print "PhoneBoogieCodeGenerator -- create boilerplate code for Boogie verification of Phone apps" @@ -29,7 +31,14 @@ def showUsage(): print "\t--controls : Phone app control info. See PhoneControlsExtractor. Short form: -c" print "\t--output : file to write with boilerplate code. Short form: -o\n" +def isAnonymousControl(control): + name= control["bplName"] + return name.find(ANONYMOUS_CONTROL_PREFIX) != -1 + def loadControlInfo(infoMap, controlClass, controlName, enabled, visible, clickHandler, checkedHandler, uncheckedHandler, selectionChangedHandler, bplName): + global anonymousControlCount + global ANONYMOUS_CONTROL_PREFIX + newControl={} newControl["class"]= controlClass newControl["enabled"]= enabled @@ -38,6 +47,10 @@ def loadControlInfo(infoMap, controlClass, controlName, enabled, visible, clickH newControl["checkedHandler"]= checkedHandler newControl["uncheckedHandler"]= uncheckedHandler newControl["selectionChangedHandler"]= selectionChangedHandler + if (bplName == ""): + # anonymous control, need a dummy boogie var, but we cannot know how it got initialized + bplName= ANONYMOUS_CONTROL_PREFIX + str(anonymousControlCount) + anonymousControlCount= anonymousControlCount+1 newControl["bplName"]=bplName infoMap[controlName]= newControl @@ -116,7 +129,7 @@ def outputPageControlDriver(file, originalPageName, boogiePageName): for entry in staticControlsMap[originalPageName]["controls"].keys(): controlInfo= staticControlsMap[originalPageName]["controls"][entry] if controlInfo["bplName"] == "": - continue + continue; if not ifInitialized: file.write("\t\tif ($activeControl == " + str(activeControl) + ") {\n") ifInitialized= True diff --git a/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py index 27517d0d..82090e29 100644 --- a/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py +++ b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py @@ -169,7 +169,7 @@ def outputPhoneControls(outputFileName): unchecked= control["Unchecked"] if (unchecked.find(COMMA_REPLACEMENT) != -1): unchecked= "" - selectionChanged= control["Unchecked"] + selectionChanged= control["SelectionChanged"] if (selectionChanged.find(COMMA_REPLACEMENT) != -1): selectionChanged= "" pageXAML= control["XAML"] diff --git a/BCT/TranslationPlugins/PhoneControlsPlugin.cs b/BCT/TranslationPlugins/PhoneControlsPlugin.cs index 168ba088..daa7c345 100644 --- a/BCT/TranslationPlugins/PhoneControlsPlugin.cs +++ b/BCT/TranslationPlugins/PhoneControlsPlugin.cs @@ -15,6 +15,7 @@ namespace TranslationPlugins { case Event.Checked: case Event.Unchecked: case Event.Click: + case Event.SelectionChanged: return new string[] { "object", "System.WindowsRoutedventArgs" }; default: throw new NotImplementedException("Handlers for event: " + controlEvent + " not supported yet"); @@ -169,6 +170,7 @@ namespace TranslationPlugins { } private void setPageAsMainPage(string pageXAML) { + pageXAML = pageXAML.ToLower(); int lastDirPos= pageXAML.LastIndexOf('/'); if (lastDirPos != -1) pageXAML = pageXAML.Substring(lastDirPos+1); @@ -199,7 +201,7 @@ namespace TranslationPlugins { foreach (KeyValuePair entry in this.pageStructureInfo) { pageClass = entry.Key; - pageXAML = entry.Value.PageXAML; + pageXAML = entry.Value.PageXAML.ToLower(); pageBoogieStringName = entry.Value.PageBoogieName; foreach (ControlInfoStructure controlInfo in entry.Value.getAllControlsInfo()) { controlClass= controlInfo.ClassName; @@ -241,7 +243,7 @@ namespace TranslationPlugins { selectionChangedHandler = ""; } bplName = controlInfo.BplName; - outputStream.WriteLine(pageClass + "," + pageXAML + "," + pageBoogieStringName + "," + controlClass + "," + controlName + "," + enabled + "," + + outputStream.WriteLine(pageClass + "," + pageXAML.ToLower() + "," + pageBoogieStringName + "," + controlClass + "," + controlName + "," + enabled + "," + visibility + "," + clickHandler + "," + checkedHandler + "," + uncheckedHandler + "," + selectionChangedHandler + "," + bplName); } @@ -273,7 +275,7 @@ namespace TranslationPlugins { ControlInfoStructure controlInfoStr; // first line just states the main page xaml - string mainPageXAML= configLine.Trim(); + string mainPageXAML= configLine.Trim().ToLower(); configLine = configStream.ReadLine(); // second line states boogie current nav variable, possibly dummy value @@ -295,7 +297,7 @@ namespace TranslationPlugins { throw new ArgumentException("Config input line contains wrong number of fields: " + inputLine.Length + ", expected " + CONFIG_LINE_FIELDS); pageClass = inputLine[PAGE_CLASS_FIELD].Trim(); - pageXAML = inputLine[PAGE_XAML_FIELD].Trim(); + pageXAML = inputLine[PAGE_XAML_FIELD].Trim().ToLower(); pageBoogieStringName = inputLine[PAGE_BOOGIE_STRING_FIELD].Trim(); controlClass = inputLine[CONTROL_CLASS_FIELD].Trim(); controlName = inputLine[CONTROL_NAME_FIELD].Trim(); -- cgit v1.2.3