Resolve() 공개 메소드

public Resolve ( ITypeResolveContext context ) : IType
context ITypeResolveContext
리턴 IType
예제 #1
0
		/// <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));
					}
				}
			}
		}
		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;
		}
예제 #3
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.");
        }