Home > Code Samples, Plug-in Development > How to edit source files of an entire Visual Studio solution using DXCore

How to edit source files of an entire Visual Studio solution using DXCore

July 4th, 2011

Usually, simple edits of text files are accomplished using the TextDocument object, which represents an open source file inside the IDE. The text document object is easy to access through the Documents DXCore service. It has lots of useful methods for editing a text like InsertText, DeleteText and SetText, which take a source code coordinates and a new text for replacement as a parameters. However, to use a text document object, it is required for the file to be opened inside the Visual Studio environment. If a file is closed, there’s no TextDocument object assigned to the file and you simply can’t use its methods. In case you are going to edit closed and/or multiple files, there’s a better way – the FileChange object (in the DevExpress.CodeRush.Core.Replacement namespace).

As the name says, the FileChange object represents a single change to a file. A file can be closed inside IDE and not even included into a project, so you can change any text file in your system. The object takes a few parameters:

  • a path to a file
  • a source range or a source point
  • a text for insertion or replacement

If you pass a source point – the specified text will be inserted at the specified position. But if you pass a source range – the text inside a file will be replaced with the new one. The FileChange class has the corresponding properties:

Property Description
Data Data, associated with a change. Used internally.
Order The order of this change in a particular file. The value is set automatically. However, if several changes are made at the same position, you can set this property to manage the order the changes are applied.
Path A full path to a file.
Range A source range of the text inside a file for replacement. If a source range has two equal source points, the text will be inserted without deletion.
Text A new text to insert or replace inside a file.

The file change object should be added into a special collection to be applied – the FileChangeCollection. Then, you can apply a collection of file changes by using the File DXCore service:

CodeRush.File.ApplyChanges(collection);

Note, if you have only a single file change, you can call the CodeRush.File.ChangeFile method instead of creating a new FileChange object. The ChangeFile method inserts, deletes or replaces the text inside the specified source file.

Usage sample

As an example, illustrating how to edit source files, let’s create a new DXCore plug-in, and add the Action DXCore control, that will modify all files of the current project by inserting a file header at the top (as a comment), if it doesn’t exist.

When the action is executed, we get the current project instance and enumerate all of its files. We check the name of every file, so it has a valid extension and it is not a designer file, nor should it already contain a header. If the file is OK, then we create a new FileChange object, specify the path to a file, a new insertion point (1,1), a file header text) and add it to a collection of file changes. When all files are enumerated, we apply the collection, so all files of the project now have a file header. Here’s the code of the plug-in:

public partial class PlugIn1 : StandardPlugIn
{
  private const string HEADER =
@"//-----------------------------------------------------------------------
// <copyright file=""{0}"" company=""My Company"">
//     Copyright (c) My Company, Inc. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
";

  private void action1_Execute(ExecuteEventArgs ea)
  {
    ProjectElement activeProject = CodeRush.Source.ActiveProject;
    if (activeProject == null)
      return;

    FileChangeCollection fileChangeCollection = new FileChangeCollection();
    foreach (SourceFile sourceFile in activeProject.AllFiles)
    {
      if (!IsValidFile(sourceFile))
        continue;

      if (ContainsFileHeader(sourceFile))
        continue;

      string filePathAndName = sourceFile.Name;
      SourcePoint insertionPoint = new SourcePoint(1, 1);
      string newHeader = String.Format(HEADER, Path.GetFileName(filePathAndName));
      FileChange fileChange = new FileChange(filePathAndName, insertionPoint, newHeader);
      fileChangeCollection.Add(fileChange);
    }
    CodeRush.File.ApplyChanges(fileChangeCollection);
  }

  private bool IsValidFile(SourceFile sourceFile)
  {
    const string EXT = ".CS";
    const string DESIGNER = ".DESIGNER";

    string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(sourceFile.Name);
    if (Path.GetExtension(fileNameWithoutExtension).ToUpper() == DESIGNER)
      return false;

    string fileExtension = Path.GetExtension(sourceFile.Name);
    return fileExtension.ToUpper() == EXT;
  }

  private bool ContainsFileHeader(SourceFile sourceFile)
  {
    LanguageElement firstChild = sourceFile.FirstChild;
    return firstChild is Comment;
  }
}

The source of a plug-in is attached (7,464 bytes, C#, Visual Studio 2010).

 
 
—–
Products: DXCore
Versions: 11.1 and up
VS IDEs: any
Updated: Nov/21/2011
ID: D100

Similar Posts: