/// <summary> /// Resolves the type by mapping the known Objective-C type information to .NET types. /// </summary> /// <returns> /// The number of unresolved types still remaining. /// </returns> /// <param name='type'> /// The NSObjectTypeInfo that contains the known Objective-C type information. /// Typically this will be the result of NSObjectInfoService.ParseHeader(). /// </param> /// <param name='provider'> /// A CodeDom provider which is used to make sure type names don't conflict with language keywords. /// </param> /// <param name='defaultNamespace'> /// The default namespace used when forcing type resolution. /// </param> public void ResolveObjcToCli (IProgressMonitor monitor, NSObjectTypeInfo type, CodeDomProvider provider, string defaultNamespace) { NSObjectTypeInfo resolved; // Resolve our base type if (type.BaseCliType == null) { if (TryResolveObjcToCli (type.BaseObjCType, out resolved)) { type.BaseCliType = resolved.CliName; } else { type.BaseCliType = defaultNamespace + "." + provider.CreateValidIdentifier (type.BaseObjCType); monitor.ReportWarning (string.Format ("Failed to resolve Objective-C type {0} to CLI type on type {1}", type.BaseObjCType, type.ObjCName)); } } // Resolve [Outlet] types foreach (var outlet in type.Outlets) { if (outlet.CliType != null) continue; if (TryResolveObjcToCli (outlet.ObjCType, out resolved)) { outlet.CliType = resolved.CliName; } else { outlet.CliType = defaultNamespace + "." + provider.CreateValidIdentifier (outlet.ObjCType); monitor.ReportWarning (string.Format ("Failed to resolve Objective-C type {0} to CLI type on outlet {1} on type {2}", outlet.ObjCType, outlet.ObjCName, type.ObjCName)); } } // Resolve [Action] param types foreach (var action in type.Actions) { foreach (var param in action.Parameters) { if (param.CliType != null) continue; if (TryResolveObjcToCli (param.ObjCType, out resolved)) { param.CliType = resolved.CliName; } else { param.CliType = defaultNamespace + "." + provider.CreateValidIdentifier (param.ObjCType); monitor.ReportWarning (string.Format ("Failed to resolve Objective-C type {0} to CLI type on action parameter {1} for action {2} on type {3}", param.ObjCType, param.Name, action.ObjCName, type.ObjCName)); } } } }
/// <summary> /// Resolves the type by mapping the known Objective-C type information to .NET types. /// </summary> /// <returns> /// The number of unresolved types still remaining. /// </returns> /// <param name='type'> /// The NSObjectTypeInfo that contains the known Objective-C type information. /// Typically this will be the result of NSObjectInfoService.ParseHeader(). /// </param> /// <param name='provider'> /// A CodeDom provider which is used to make sure type names don't conflict with language keywords. /// </param> /// <param name='defaultNamespace'> /// The default namespace used when forcing type resolution. /// </param> public void ResolveObjcToCli (IProgressMonitor monitor, NSObjectTypeInfo type, CodeDomProvider provider, string defaultNamespace) { NSObjectTypeInfo resolved; // Resolve our base type if (type.BaseCliType == null) { if (TryResolveObjcToCli (type.BaseObjCType, out resolved)) { type.BaseCliType = resolved.CliName; } else { var reference = new GetClassTypeReference (defaultNamespace, provider.CreateValidIdentifier (type.BaseObjCType)); type.BaseCliType = reference.Resolve (dom.Compilation).ReflectionName; var message = string.Format ("Failed to resolve Objective-C type '{0}' to a type in the current solution.", type.BaseObjCType); message += string.Format (" Adding a [Register (\"{0}\")] attribute to the class which corresponds to this will allow it to be synced to Objective-C.", type.BaseObjCType); monitor.ReportError (null, new UserException ("Error while syncing", message)); } } // Resolve [Outlet] types foreach (var outlet in type.Outlets) { if (outlet.CliType != null) continue; if (TryResolveObjcToCli (outlet.ObjCType, out resolved)) { outlet.CliType = resolved.CliName; } else { outlet.CliType = defaultNamespace + "." + provider.CreateValidIdentifier (outlet.ObjCType); var message = string.Format ("Failed to resolve Objective-C outlet '{0}' of type '{1}' to a type in the current solution.", outlet.ObjCName, outlet.ObjCType); message += string.Format (" Adding a [Register (\"{0}\")] attribute to the class which corresponds to this will allow it to be synced to Objective-C.", outlet.ObjCType); monitor.ReportError (null, new UserException ("Error while syncing", message)); } } // Resolve [Action] param types foreach (var action in type.Actions) { foreach (var param in action.Parameters) { if (param.CliType != null) continue; if (TryResolveObjcToCli (param.ObjCType, out resolved)) { param.CliType = resolved.CliName; } else { param.CliType = defaultNamespace + "." + provider.CreateValidIdentifier (param.ObjCType); var message = string.Format ("Failed to resolve paramater '{0}' of type '{2}' on Objective-C action '{1}' to a type in the current solution.", param.Name, action.ObjCName, param.ObjCType); message += string.Format (" Adding a [Register (\"{0}\")] attribute to the class which corresponds to this will allow it to be synced to Objective-C.", param.ObjCType); monitor.ReportError (null, new UserException ("Error while syncing", message)); } } } }
private static string VerifyResourceName(string key, CodeDomProvider provider, bool isNameSpace) { if (key == null) { throw new ArgumentNullException("key"); } if (provider == null) { throw new ArgumentNullException("provider"); } foreach (char ch in CharsToReplace) { if (!isNameSpace || ((ch != '.') && (ch != ':'))) { key = key.Replace(ch, '_'); } } if (provider.IsValidIdentifier(key)) { return key; } key = provider.CreateValidIdentifier(key); if (provider.IsValidIdentifier(key)) { return key; } key = "_" + key; if (provider.IsValidIdentifier(key)) { return key; } return null; }
public Dictionary<string, List<NSObjectTypeInfo>> GetTypeUpdates (IProgressMonitor monitor, CodeDomProvider provider, out Dictionary<string, NSObjectTypeInfo> newTypes, out Dictionary<string, ProjectFile> newFiles) { Dictionary<string, List<NSObjectTypeInfo>> designerFiles = new Dictionary<string, List<NSObjectTypeInfo>> (); string defaultNamespace; // First, we need to name any new user-defined types. foreach (var job in TypeSyncJobs) { if (!job.IsFreshlyAdded) { monitor.Log.WriteLine ("Found updated class: {0}", job.Type.CliName); continue; } defaultNamespace = Project.GetDefaultNamespace (job.RelativePath); job.Type.CliName = defaultNamespace + "." + provider.CreateValidIdentifier (job.Type.ObjCName); monitor.Log.WriteLine ("Found newly-added class: {0}", job.Type.CliName); ProjectInfo.InsertUpdatedType (job.Type); } // Next we can resolve base-types, outlet types, and action parameter types for each of our user-defined types. foreach (var job in TypeSyncJobs) { defaultNamespace = Project.GetDefaultNamespace (job.RelativePath); ProjectInfo.ResolveObjcToCli (monitor, job.Type, provider, defaultNamespace); } AggregateTypeUpdates (monitor, provider, designerFiles, out newTypes, out newFiles); MergeExistingTypes (designerFiles); return designerFiles; }
public static string VerifyResourceName (string key, CodeDomProvider provider) { string keyToUse; char [] charKey; // check params if (key == null) throw new ArgumentNullException ("Parameter: key must not be null"); if (provider == null) throw new ArgumentNullException ("Parameter: provider must not be null"); if (key == String.Empty) { keyToUse = "_"; } else { // replaces special chars charKey = key.ToCharArray (); for (int i = 0; i < charKey.Length; i++) charKey [i] = VerifySpecialChar (charKey [i]); keyToUse = new string(charKey); } // resolve if keyword keyToUse = provider.CreateValidIdentifier (keyToUse); // check if still not valid for provider if (provider.IsValidIdentifier (keyToUse)) return keyToUse; else return null; }
static void GenerateAction (CodeTypeDeclaration type, string name, CodeTypeReference senderType, CodeDomProvider provider, CodeGeneratorOptions generatorOptions, ref StringWriter actionStubWriter) { if (provider is Microsoft.CSharp.CSharpCodeProvider) { type.Members.Add (new CodeSnippetTypeMember ("[MonoTouch.Foundation.Export(\"" + name + "\")]")); type.Members.Add (new CodeSnippetTypeMember ( String.Format ("partial void {1} ({2} sender);\n", name, provider.CreateValidIdentifier (name.TrimEnd (':')), senderType.BaseType))); return; } else if (provider.FileExtension == "pas") { var m = new CodeMemberMethod (); m.Name = provider.CreateValidIdentifier (name.TrimEnd (':')); m.Parameters.Add (new CodeParameterDeclarationExpression (senderType.BaseType, "sender")); m.UserData ["OxygenePartial"] = "YES"; m.UserData ["OxygeneEmpty"] = "YES"; var a = new CodeAttributeDeclaration ("MonoTouch.Foundation.Export"); a.Arguments.Add (new CodeAttributeArgument (new CodePrimitiveExpression (name))); m.CustomAttributes.Add (a); type.Members.Add (m); return; } var meth = CreateEventMethod (name, senderType); bool actionStubWriterCreated = false; if (actionStubWriter == null) { actionStubWriterCreated = true; actionStubWriter = new StringWriter (); actionStubWriter.WriteLine ("Action method stubs:"); actionStubWriter.WriteLine (); } try { provider.GenerateCodeFromMember (meth, actionStubWriter, generatorOptions); actionStubWriter.WriteLine (); } catch { //clear the header if generation failed if (actionStubWriterCreated) actionStubWriter = null; } }
public static CodeCompileUnit Create (IDictionary resourceList, string baseName, string generatedCodeNamespace, string resourcesNamespace, CodeDomProvider codeProvider, bool internalClass, out string [] unmatchable) { string baseNameToUse, generatedCodeNamespaceToUse; string resourcesToUse; // validate parameters, convert into useable form where necessary / possible if (resourceList == null) throw new ArgumentNullException ("Parameter resourceList must not be null"); if (codeProvider == null) throw new ArgumentNullException ("Parameter: codeProvider must not be null"); if (baseName == null) throw new ArgumentNullException ("Parameter: baseName must not be null"); baseNameToUse = VerifyResourceName (baseName, codeProvider); if (baseNameToUse == null) throw new ArgumentException ("Parameter: baseName is invalid"); if (generatedCodeNamespace == null) { generatedCodeNamespaceToUse = ""; } else { generatedCodeNamespaceToUse = CleanNamespaceChars (generatedCodeNamespace); generatedCodeNamespaceToUse = codeProvider.CreateValidIdentifier ( generatedCodeNamespaceToUse); } if (resourcesNamespace == null) resourcesToUse = generatedCodeNamespaceToUse + "." + baseNameToUse; else if (resourcesNamespace == String.Empty) resourcesToUse = baseNameToUse; else resourcesToUse = resourcesNamespace + "." + baseNameToUse; // validate ResourceList IDictionary Dictionary<string,ResourceItem> resourceItemDict; resourceItemDict = new Dictionary<string,ResourceItem> (StringComparer.OrdinalIgnoreCase); //allow ArgumentException to be raised on case insensitive dupes,InvalidCastException on key not being string foreach (DictionaryEntry de in resourceList) resourceItemDict.Add ((string) de.Key, new ResourceItem (de.Value)); ProcessResourceList (resourceItemDict, codeProvider); // Generate CodeDOM CodeCompileUnit ccu = GenerateCodeDOMBase (baseNameToUse, generatedCodeNamespaceToUse, resourcesToUse, internalClass); // add properties for resources unmatchable = ResourcePropertyGeneration (ccu.Namespaces [0].Types [0], resourceItemDict, internalClass); return ccu; }
private static string VerifyResourceName(string key, CodeDomProvider provider, bool isNameSpace) { if (null == key) throw new ArgumentNullException("key"); if (null == provider) throw new ArgumentNullException("provider"); for (int index = 0; index < charsToReplace.Length; index++) { char ch = charsToReplace[index]; if (!isNameSpace || ((ch != '.') && (ch != ':'))) key = key.Replace(ch, ReplacementChar); } if (provider.IsValidIdentifier(key)) return key; key = provider.CreateValidIdentifier(key); if (provider.IsValidIdentifier(key)) return key; key = "_" + key; if (provider.IsValidIdentifier(key)) return key; return null; }
public static string MakeSafeName (string name, CodeDomProvider provider) { if (name == null || provider == null) throw new NullReferenceException (); name = provider.CreateValidIdentifier (name); return MakeSafeNameInternal (name); }
// Once CodeDom provides a way to verify a namespace name, revisit this method. private static String VerifyResourceName(String key, CodeDomProvider provider, bool isNameSpace) { if (key == null) throw new ArgumentNullException("key"); if (provider == null) throw new ArgumentNullException("provider"); foreach(char c in CharsToReplace) { // For namespaces, allow . and :: if (!(isNameSpace && (c == '.' || c == ':'))) key = key.Replace(c, ReplacementChar); } if (provider.IsValidIdentifier(key)) return key; // Now try fixing up keywords like "for". key = provider.CreateValidIdentifier(key); if (provider.IsValidIdentifier(key)) return key; // make one last ditch effort by prepending _. This fixes keys that start with a number key = "_" + key; if (provider.IsValidIdentifier(key)) return key; return null; }
private static string VerifyResourceName(string name, CodeDomProvider provider, bool isNameSpace) { if (null == name) throw new ArgumentNullException("name"); if (null == provider) throw new ArgumentNullException("provider"); for (int index = 0; index < _charsToReplace.Length; index++) { char ch = _charsToReplace[index]; if (!isNameSpace || ((ch != '.') && (ch != ':'))) name = name.Replace(ch, ReplacementChar); } if (provider.IsValidIdentifier(name)) return name; name = provider.CreateValidIdentifier(name); if (provider.IsValidIdentifier(name)) return name; name = "_" + name; if (provider.IsValidIdentifier(name)) return name; return null; }