public CSharpProject(Solution solution, string title, string fileName)
        {
            // Normalize the file name
            fileName = Path.GetFullPath(fileName);

            this.Solution = solution;
            this.Title = title;
            this.FileName = fileName;

            // Use MSBuild to open the .csproj
            var msbuildProject = new Microsoft.Build.Evaluation.Project(fileName);
            // Figure out some compiler settings
            this.AssemblyName = msbuildProject.GetPropertyValue("AssemblyName");
            this.CompilerSettings.AllowUnsafeBlocks = GetBoolProperty(msbuildProject, "AllowUnsafeBlocks") ?? false;
            this.CompilerSettings.CheckForOverflow = GetBoolProperty(msbuildProject, "CheckForOverflowUnderflow") ?? false;
            string defineConstants = msbuildProject.GetPropertyValue("DefineConstants");
            foreach (string symbol in defineConstants.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                this.CompilerSettings.ConditionalSymbols.Add(symbol.Trim());

            // Initialize the unresolved type system
            IProjectContent pc = new CSharpProjectContent();
            pc = pc.SetAssemblyName(this.AssemblyName);
            pc = pc.SetProjectFileName(fileName);
            pc = pc.SetCompilerSettings(this.CompilerSettings);

            // Parse the C# code files
            foreach (var item in msbuildProject.GetItems("Compile")) {
                var file = new CSharpFile(this, Path.Combine(msbuildProject.DirectoryPath, item.EvaluatedInclude));
                Files.Add(file);
            }
            // Add parsed files to the type system
            pc = pc.AddOrUpdateFiles(Files.Select(f => f.UnresolvedTypeSystemForFile));

            // Add referenced assemblies:
            foreach (string assemblyFile in ResolveAssemblyReferences(msbuildProject)) {
                IUnresolvedAssembly assembly = solution.LoadAssembly(assemblyFile);
                pc = pc.AddAssemblyReferences(new [] { assembly });
            }

            // Add project references:
            foreach (var item in msbuildProject.GetItems("ProjectReference")) {
                string referencedFileName = Path.Combine(msbuildProject.DirectoryPath, item.EvaluatedInclude);
                // Normalize the path; this is required to match the name with the referenced project's file name
                referencedFileName = Path.GetFullPath(referencedFileName);
                pc = pc.AddAssemblyReferences(new[] { new ProjectReference(referencedFileName) });
            }
            this.ProjectContent = pc;
        }
示例#2
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.");
        }