Inheritance: ITypeReference, ISymbolReference, ISupportsInterning
		public NSObjectInfoService (string wrapperRoot)
		{
			this.WrapperRoot = wrapperRoot;
			var typeNamespace = wrapperRoot + ".Foundation";
			connectAttType = new GetClassTypeReference (typeNamespace, "ConnectAttribute");
			exportAttType = new GetClassTypeReference (typeNamespace, "ExportAttribute");
			iboutletAttType = new GetClassTypeReference (typeNamespace, "OutletAttribute");
			ibactionAttType = new GetClassTypeReference (typeNamespace, "ActionAttribute");
			registerAttType = new GetClassTypeReference (typeNamespace, "RegisterAttribute");
			modelAttType = new GetClassTypeReference (typeNamespace, "ModelAttribute");
			nsobjectType = new GetClassTypeReference (typeNamespace, "NSObject");
		}
			public string GetShortType (string ns, string name, int typeArguments = 0)
			{
				if (Document == null || Document.ParsedDocument == null)
					return ns + "." + name;
				var typeDef = new GetClassTypeReference (ns, name, typeArguments).Resolve (Document.Compilation.TypeResolveContext);
				if (typeDef == null)
					return ns + "." + name;
				var file = Document.ParsedDocument.ParsedFile as CSharpUnresolvedFile;
				var csResolver = file.GetResolver (Document.Compilation, Document.Editor.Caret.Location);
				var builder = new ICSharpCode.NRefactory.CSharp.Refactoring.TypeSystemAstBuilder (csResolver);
				return OutputNode (Document, builder.ConvertType (typeDef));
			}
		protected override string GenerateCode(ITypeDefinition currentClass)
		{
			bool implementInterface = this.implementInterface.IsChecked == true;
			bool hasOnPropertyChanged = HasOnPropertyChanged(currentClass);
			bool useEventArgs = false;
			
			AstNode insertionAnchorElement = refactoringContext.GetNode();
			if ((insertionAnchorElement == null) || !(insertionAnchorElement.Parent is TypeDeclaration)) {
				return null;
			}
			NewLineNode newLineNode = insertionAnchorElement as NewLineNode;
			while (insertionAnchorElement.PrevSibling is NewLineNode)
				insertionAnchorElement = insertionAnchorElement.PrevSibling ?? insertionAnchorElement;
			
			using (Script script = refactoringContext.StartScript()) {
				TypeDeclaration currentClassDeclaration = insertionAnchorElement.Parent as TypeDeclaration;
				
				if (implementInterface && !currentClass.IsStatic) {
					if (!hasOnPropertyChanged) {
						var nodes = new List<AstNode>();
						if (!currentClass.GetAllBaseTypeDefinitions().Any(bt => bt.FullName == "System.ComponentModel.INotifyPropertyChanged")) {
							AstNode nodeBeforeClassBlock = currentClassDeclaration.LBraceToken;
							if (nodeBeforeClassBlock.PrevSibling is NewLineNode) {
								// There's a new line before the brace, insert before it!
								nodeBeforeClassBlock = nodeBeforeClassBlock.PrevSibling;
							}
							int insertion = editor.Document.GetOffset(nodeBeforeClassBlock.StartLocation);
							
							AstType interfaceTypeNode = refactoringContext.CreateShortType("System.ComponentModel", "INotifyPropertyChanged", 0);
							var directBaseTypes = currentClass.DirectBaseTypes.Where(t => t.FullName != "System.Object");
							if (currentClassDeclaration.BaseTypes.Count > 0) {
								script.InsertText(insertion, ", " + interfaceTypeNode + " ");
							} else {
								script.InsertText(insertion, " : " + interfaceTypeNode + " ");
							}
						}

						var rt = new GetClassTypeReference("System.ComponentModel", "INotifyPropertyChanged", 0);
						var rtResolved = rt.Resolve(refactoringContext.Compilation);
						var ev = rtResolved.GetEvents().First(e => e.Name == "PropertyChanged");
						
						EventDeclaration propertyChangedEvent = new EventDeclaration();
						propertyChangedEvent.Variables.Add(new VariableInitializer(ev.Name));
						propertyChangedEvent.Modifiers = Modifiers.Public;
						propertyChangedEvent.ReturnType = refactoringContext.CreateShortType(ev.ReturnType);
						
						nodes.Add(propertyChangedEvent);
						
						MethodDeclaration onEvent = CreateOnEventMethod(ev, currentClass);
						nodes.Add(onEvent);
						foreach (var node in nodes) {
							script.InsertAfter(insertionAnchorElement, node);
							AppendNewLine(script, insertionAnchorElement, newLineNode);
						}
						useEventArgs = false;
					} else {
						useEventArgs = currentClass.GetMethods().First(m => m.Name == "OnPropertyChanged").Parameters[0].Type.FullName != "System.String";
					}
				}
				
				foreach (FieldWrapper field in fields.Where(f => f.IsIncluded)) {
					var prop = CreateProperty(field.Field, true, field.AddSetter);
					if (!field.Field.IsStatic && !currentClass.IsStatic && field.AddSetter && implementInterface) {
						var invocation = new ExpressionStatement(CreateInvocation(field.PropertyName, useEventArgs));
						var assignment = prop.Setter.Body.Children.ElementAt(0) as Statement;
						prop.Setter.Body = new BlockStatement();
						BlockStatement elseBlock = new BlockStatement();
						elseBlock.Add(assignment.Clone());
						elseBlock.Add(invocation);
						prop.Setter.Body.Add(
							new IfElseStatement(
								new BinaryOperatorExpression(new IdentifierExpression(field.MemberName), BinaryOperatorType.InEquality, new IdentifierExpression("value")),
								elseBlock
							)
						);
					}
					
					script.InsertAfter(insertionAnchorElement, prop);
					AppendNewLine(script, insertionAnchorElement, newLineNode);
				}
			}
			
			return null;
		}
Example #4
0
        bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
        {
            GetClassTypeReference o = other as GetClassTypeReference;

            return(o != null && assembly == o.assembly && name == o.name && nameSpace == o.nameSpace && typeParameterCount == o.typeParameterCount);
        }
		/// <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));
					}
				}
			}
		}
Example #6
0
        public static void Main(string[] args)
        {
            if (args.Length != 4)
            {
                Console.WriteLine("use: RenameClass.exe <SolutionPath> <ClassNamespace> <CurrentClassName> <NewClassName>");
                return;
            }

            var solutionFile = args[0]; // "C:\\Users\\v-ezeqs\\Documents\\Visual Studio 2010\\Projects\\Application36\\Application36.sln"
            var classNamespace = args[1]; // "Application36.WebHost"
            var className = args[2]; // "SiteMaster"
            var classNewName = args[3]; // "SiteMaster2"

            if (!File.Exists(solutionFile))
            {
                Console.WriteLine("Solution not found at {0}", solutionFile);
                return;
            }

            Console.WriteLine("Loading solution...");

            // Loading Solution in Memory
            Solution solution = new Solution(solutionFile);

            Console.WriteLine("Finding references...");

            // Define which Type I'm looking for
            var typeReference = new GetClassTypeReference(classNamespace, className) as ITypeReference;

            // Try to find the Type definition in solution's projects
            foreach (var proj in solution.Projects)
            {
                var type = typeReference.Resolve(proj.Compilation);
                if (type.Kind != TypeKind.Unknown)
                {
                    SetSearchedMembers(new List<object>() { type });
                }
            }

            if (searchedMembers == null)
            {
                Console.WriteLine("Not References found. Refactoring Done.");
                return;
            }

            // Find all related members related with the Type (like Members, Methods, etc)
            ICSharpCode.NRefactory.CSharp.Resolver.FindReferences refFinder = new ICSharpCode.NRefactory.CSharp.Resolver.FindReferences();
            var scopes = searchedMembers.Select (e => refFinder.GetSearchScopes (e as IEntity));

            // Finding references to the Type on the one of the different Solution files
            refs = new List<dynamic>();
            foreach (var file in solution.AllFiles.Distinct (new CSharpFileEqualityComparer())) {
                foreach (var scope in scopes)
                {
                    refFinder.FindReferencesInFile(
                        scope,
                        file.UnresolvedTypeSystemForFile,
                        file.SyntaxTree,
                        file.Project.Compilation,
                        (astNode, result) =>
                        {
                            var newRef = GetReference(result, astNode, file);
                            if (newRef == null || refs.Any(r => r.File.FileName == newRef.File.FileName && r.Region == newRef.Region))
                                return;
                            refs.Add(newRef);
                        },
                        CancellationToken.None
                    );
                }
            }

            Console.WriteLine("Refactoring {0} places in {1} files...",
                              refs.Count(),
                              refs.Select(x => x.File.FileName).Distinct().Count());

            // Perform replace for each of the References found
            foreach (var r in refs) {
                // DocumentScript expects the the AST to stay unmodified (so that it fits
                // to the document state at the time of the DocumentScript constructor call),
                // so we call Freeze() to prevent accidental modifications (e.g. forgetting a Clone() call).
                r.File.SyntaxTree.Freeze();

                // Create a document containing the file content:
                var fileText = File.ReadAllText(r.File.FileName);
                var document = new StringBuilderDocument(fileText);
                using (var script = new DocumentScript(document, FormattingOptionsFactory.CreateAllman(), new TextEditorOptions())) {
                    // Alternative 1: clone a portion of the AST and modify it
                    //var copy = (InvocationExpression)expr.Clone();
                    //copy.Arguments.Add(stringComparisonAst.Member("Ordinal"));
                    //script.Replace(expr, copy);

                    // Alternative 2: perform direct text insertion / replace
                    int offset = script.GetCurrentOffset(r.Region.Begin);
                    var length = r.Region.End.Column - r.Region.Begin.Column;

                    script.Replace(offset, length, classNewName);
                }
                File.WriteAllText(r.File.FileName, document.Text);
            }

            Console.WriteLine("Refactoring Done.");
        }
        bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
        {
            GetClassTypeReference o = other as GetClassTypeReference;

            return(o != null && assembly == o.assembly && fullTypeName == o.fullTypeName);
        }
		static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, IEntity entity)
		{
			if (pos == reflectionTypeName.Length)
				throw new ReflectionNameParseException(pos, "Unexpected end");
			if (reflectionTypeName[pos] == '`') {
				// type parameter reference
				pos++;
				if (pos == reflectionTypeName.Length)
					throw new ReflectionNameParseException(pos, "Unexpected end");
				if (reflectionTypeName[pos] == '`') {
					// method type parameter reference
					pos++;
					int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
					IMethod method = entity as IMethod;
					if (method != null && index >= 0 && index < method.TypeParameters.Count)
						return method.TypeParameters[index];
					else
						return SharedTypes.UnknownType;
				} else {
					// class type parameter reference
					int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
					ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null);
					if (c != null && index >= 0 && index < c.TypeParameters.Count)
						return c.TypeParameters[index];
					else
						return SharedTypes.UnknownType;
				}
			}
			// not a type parameter reference: read the actual type name
			int tpc;
			string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc);
			ITypeReference reference = new GetClassTypeReference(typeName, tpc);
			// read type suffixes
			while (pos < reflectionTypeName.Length) {
				switch (reflectionTypeName[pos++]) {
					case '+':
						typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc);
						reference = new NestedTypeReference(reference, typeName, tpc);
						break;
					case '*':
						reference = new PointerTypeReference(reference);
						break;
					case '&':
						reference = new ByReferenceTypeReference(reference);
						break;
					case '[':
						// this might be an array or a generic type
						if (pos == reflectionTypeName.Length)
							throw new ReflectionNameParseException(pos, "Unexpected end");
						if (reflectionTypeName[pos] == '[') {
							// it's a generic type
							List<ITypeReference> typeArguments = new List<ITypeReference>(tpc);
							pos++;
							typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity));
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
								pos++;
							else
								throw new ReflectionNameParseException(pos, "Expected end of type argument");
							
							while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') {
								pos++;
								if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[')
									pos++;
								else
									throw new ReflectionNameParseException(pos, "Expected another type argument");
								
								typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity));
								
								if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
									pos++;
								else
									throw new ReflectionNameParseException(pos, "Expected end of type argument");
							}
							
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') {
								pos++;
								reference = new ParameterizedTypeReference(reference, typeArguments);
							} else {
								throw new ReflectionNameParseException(pos, "Expected end of generic type");
							}
						} else {
							// it's an array
							int dimensions = 1;
							while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') {
								dimensions++;
								pos++;
							}
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') {
								pos++; // end of array
								reference = new ArrayTypeReference(reference, dimensions);
							} else {
								throw new ReflectionNameParseException(pos, "Invalid array modifier");
							}
						}
						break;
					case ',':
						// assembly qualified name, ignore everything up to the end/next ']'
						while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']')
							pos++;
						break;
					default:
						pos--; // reset pos to the character we couldn't read
						if (reflectionTypeName[pos] == ']')
							return reference; // return from a nested generic
						else
							throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'");
				}
			}
			return reference;
		}
Example #9
0
        public IUnresolvedAssembly LoadAssembly(Assembly assembly)
        {
            if (assembly == null)
                throw new ArgumentNullException ("assembly");

            // Read assembly and module attributes
            IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>();
            IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>();
            AddAttributes(assembly, assemblyAttributes);
            AddAttributes(assembly.ManifestModule, moduleAttributes);

            assemblyAttributes = interningProvider.InternList(assemblyAttributes);
            moduleAttributes = interningProvider.InternList(moduleAttributes);

            currentAssemblyDefinition = assembly;
            currentAssembly = new IkvmUnresolvedAssembly (assembly.FullName, DocumentationProvider);
            currentAssembly.Location = assembly.Location;
            currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes);
            currentAssembly.ModuleAttributes.AddRange(moduleAttributes);
            // Register type forwarders:
            foreach (var type in assembly.ManifestModule.__GetExportedTypes ()) {
                if (type.Assembly != assembly) {
                    int typeParameterCount;
                    string ns = type.Namespace;
                    string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
                    ns = interningProvider.Intern(ns);
                    name = interningProvider.Intern(name);
                    var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Assembly), ns, name, typeParameterCount);
                    typeRef = interningProvider.Intern(typeRef);
                    var key = new TopLevelTypeName(ns, name, typeParameterCount);
                    currentAssembly.AddTypeForwarder(key, typeRef);
                }
            }

            // Create and register all types:
            var ikvmTypeDefs = new List<IKVM.Reflection.Type>();
            var typeDefs = new List<DefaultUnresolvedTypeDefinition>();

            foreach (var td in assembly.GetTypes ()) {
                if (td.DeclaringType != null)
                    continue;
                CancellationToken.ThrowIfCancellationRequested();

                if (IncludeInternalMembers || td.IsPublic) {
                    string name = td.Name;
                    if (name.Length == 0)
                        continue;

                    var t = CreateTopLevelTypeDefinition(td);
                    ikvmTypeDefs.Add(td);
                    typeDefs.Add(t);
                    currentAssembly.AddTypeDefinition(t);
                    // The registration will happen after the members are initialized
                }
            }

            // Initialize the type's members:
            for (int i = 0; i < typeDefs.Count; i++) {
                InitTypeDefinition(ikvmTypeDefs[i], typeDefs[i]);
            }

            // Freezing the assembly here is important:
            // otherwise it will be frozen when a compilation is first created
            // from it. But freezing has the effect of changing some collection instances
            // (to ReadOnlyCollection). This hidden mutation was causing a crash
            // when the FastSerializer was saving the assembly at the same time as
            // the first compilation was created from it.
            // By freezing the assembly now, we ensure it is usable on multiple
            // threads without issues.
            currentAssembly.Freeze();

            var result = currentAssembly;
            currentAssembly = null;
            return result;
        }
		public string GetSimpleTypeName (string fullTypeName)
		{
			if (CurrentContext.ParsedDocument == null)
				return fullTypeName.Replace ("#", ".");
			string ns = "";
			string name = "";
			string member = "";
			
			int idx = fullTypeName.IndexOf ('#');
			if (idx < 0) {
				name = fullTypeName;
			} else {
				ns = fullTypeName.Substring (0, idx);
				name = fullTypeName.Substring (idx + 1);
			}
			
			idx = name.IndexOf ('.');
			if (idx >= 0) {
				member = name.Substring (idx);
				name = name.Substring (0, idx);
			}

			var type = new GetClassTypeReference (ns, name, 0).Resolve (
				CurrentContext.Document.ParsedDocument.GetTypeResolveContext (
				CurrentContext.Document.Compilation, 
				CurrentContext.Document.Editor.Caret.Location
				)
			);
			bool stripAttribute = false;
			if (type == null || type.Kind == TypeKind.Unknown) {
				type = new GetClassTypeReference (ns, name + "Attribute", 0).Resolve (
					CurrentContext.Document.ParsedDocument.GetTypeResolveContext (
					CurrentContext.Document.Compilation, 
					CurrentContext.Document.Editor.Caret.Location
					)
				);	
				stripAttribute = true;
			}
			if (type == null || type.Kind == TypeKind.Unknown)
				return fullTypeName.Replace ("#", ".");
			var generator = CodeGenerator.CreateGenerator (CurrentContext.Document);
			if (generator != null) {
				var result = generator.GetShortTypeString (CurrentContext.Document, type) + member;
				if (stripAttribute && result.EndsWith ("Attribute", StringComparison.Ordinal))
				    result = result.Substring (0, result.Length - "Attribute".Length);
				return result;
			}
			return fullTypeName.Replace ("#", ".");
		}
		ICodeContext CreateContext(ITextEditor editor)
		{
			var compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
			var project = SD.ProjectService.FindProjectContainingFile(editor.FileName);
			
			var resolveContext = new SimpleTypeResolveContext(compilation.MainAssembly);
			
			var currentTypeDefinition = new DefaultUnresolvedTypeDefinition(project.RootNamespace, Path.GetFileNameWithoutExtension(editor.FileName));
			ITypeReference baseTypeReference = new GetClassTypeReference("System.Web.Mvc", "WebViewPage", 1);
			baseTypeReference = new ParameterizedTypeReference(baseTypeReference, new[] { FindModelType(editor) });
			currentTypeDefinition.BaseTypes.Add(baseTypeReference);
			
			var currentMethod = new DefaultUnresolvedMethod(currentTypeDefinition, "__ContextStub__");
			currentMethod.ReturnType = KnownTypeReference.Void;
			currentTypeDefinition.Members.Add(currentMethod);
			
			var currentResolvedTypeDef = new DefaultResolvedTypeDefinition(resolveContext, currentTypeDefinition);
			
			var projectContent = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
			
			var currentFile = new CSharpUnresolvedFile();
			
			currentFile.RootUsingScope.AddSimpleUsing("System.Web.Mvc");
			currentFile.RootUsingScope.AddSimpleUsing("System.Web.Mvc.Ajax");
			currentFile.RootUsingScope.AddSimpleUsing("System.Web.Mvc.Html");
			currentFile.RootUsingScope.AddSimpleUsing("System.Web.Routing");
			
			currentFile.TopLevelTypeDefinitions.Add(currentTypeDefinition);
			
			if (projectContent != null) {
				compilation = projectContent.AddOrUpdateFiles(currentFile).CreateCompilation(SD.ParserService.GetCurrentSolutionSnapshot());
			}
			
			var context = new CSharpTypeResolveContext(compilation.MainAssembly,
			                                           currentFile.RootUsingScope.Resolve(compilation),
			                                           currentResolvedTypeDef,
			                                           currentMethod.CreateResolved(resolveContext.WithCurrentTypeDefinition(currentResolvedTypeDef)));
			return new CSharpResolver(context);
		}