/// <summary>
        /// Takes a configuration and a description of a using directive list, and
        /// produces two things: a list containing just the directives (with the
        /// items representing blank lines removed), and a description of the
        /// correct order and grouping for these items for the given configuration.
        /// </summary>
        /// <param name="configuration">The configuration that will determine the
        /// correct order and grouping.</param>
        /// <param name="items">A list of using directives and the blank lines
        /// interspersed therein. (To simplify processing, this may be null to
        /// represent the absence of any using directives.)</param>
        /// <param name="imports">The 'flattened' list (just the using directives,
        /// with any blank lines stripped out) will be written to this argument,
        /// unless <c>items</c> is null, in which case this will be set to null.</param>
        /// <param name="requiredOrderByGroups">The correct ordering and spacing
        /// for the using directives (as determined by the configuration) will be
        /// written to this argument (unless <c>items</c> is null, in which case
        /// this will be set to null).</param>
        /// <remarks>
        /// The correct order and spacing is represented as a list of lists. Each
        /// nested list represents a group of usings, where each group should be
        /// separated by a blank line.
        /// </remarks>
        public static void FlattenImportsAndDetermineOrderAndSpacing(
            OrderUsingsConfiguration configuration,
            List<UsingDirectiveOrSpace> items,
            out List<UsingDirective> imports,
            out List<List<UsingDirective>> requiredOrderByGroups)
        {
            imports = null;
            requiredOrderByGroups = null;
            if (items != null)
            {
                imports = items
                    .Where(i => !i.IsBlankLine)
                    .Select(i => i.Directive)
                    .ToList();

                requiredOrderByGroups =
                    OrderAndSpacingGenerator.DetermineOrderAndSpacing(imports, configuration);
            }
        }
Пример #2
0
        /// <summary>
        /// Fixes the order of the using directives in a given file or namespace block
        /// to match the specified configuration.
        /// </summary>
        /// <param name="holder">The file or namespace block in which to fix the order
        /// of using directives (if any are present).</param>
        /// <param name="configuration">The configuration determining the correct order.</param>
        public static void FixOrder(
            ICSharpTypeAndNamespaceHolderDeclaration holder,
            OrderUsingsConfiguration configuration)
        {
            // The reordering proceeds one item at a time, so we just keep reapplying it
            // until there's nothing left to do.
            // To avoid hanging VS in the event that an error in the logic causes the
            // sequence of modifications not to terminate, we ensure we don't try to
            // apply more changes than there are using directives.
            int tries = 0;
            int itemCount = 0;
            while (tries == 0 || tries <= itemCount)
            {
                List<UsingDirectiveOrSpace> items = ImportReader.ReadImports(holder);
                List<UsingDirective> imports;
                List<List<UsingDirective>> requiredOrderByGroups;
                ImportInspector.FlattenImportsAndDetermineOrderAndSpacing(
                    configuration, items, out imports, out requiredOrderByGroups);

                if (requiredOrderByGroups == null)
                {
                    break;
                }

                itemCount = imports.Count;
                Relocation nextChange = ImportInspector.GetNextUsingToMove(requiredOrderByGroups, imports);
                if (nextChange != null)
                {
                    IUsingDirective toMove = holder.Imports[nextChange.From];
                    IUsingDirective before = holder.Imports[nextChange.To];
                    holder.RemoveImport(toMove);
                    holder.AddImportBefore(toMove, before);
                    tries += 1;
                }
                else
                {
                    break;
                }
            }
        }
 /// <summary>
 /// Initializes a <see cref="UsingOrderHighlighting"/>.
 /// </summary>
 /// <param name="typeAndNamespaceHolder">The file or namespace block that contains
 /// the import list being highlighted.</param>
 /// <param name="config">The configuration that was active when we determined that
 /// the import list does not match the requirements.</param>
 internal UsingOrderHighlighting(
     ICSharpTypeAndNamespaceHolderDeclaration typeAndNamespaceHolder, OrderUsingsConfiguration config)
     : base(typeAndNamespaceHolder, config)
 {
 }
 /// <summary>
 /// Initializes a <see cref="OrderUsingsDaemonStageProcess"/>.
 /// </summary>
 /// <param name="process">The process object supplied by R# for this work.</param>
 /// <param name="file">The file to process.</param>
 /// <param name="config">The order and spacing configuration to use.</param>
 public OrderUsingsDaemonStageProcess(IDaemonProcess process, ICSharpFile file, OrderUsingsConfiguration config)
 {
     _file = file;
     _config = config;
     DaemonProcess = process;
 }
Пример #5
0
        /// <summary>
        /// Fixes the spacing of the using directives in a given file or namespace block
        /// to match the specified configuration. (The directives must already be in
        /// the correct order.)
        /// </summary>
        /// <param name="holder">The file or namespace block in which to fix the spacing
        /// of using directives (if any are present).</param>
        /// <param name="configuration">The configuration determining the correct spacing.</param>
        public static void FixSpacing(
            ICSharpTypeAndNamespaceHolderDeclaration holder,
            OrderUsingsConfiguration configuration)
        {
            // The reordering proceeds one item at a time, so we just keep reapplying it
            // until there's nothing left to do.
            // To avoid hanging VS in the event that an error in the logic causes the
            // sequence of modifications not to terminate, we ensure we don't try to
            // apply more changes than there are either using directives or blank
            // lines in the usings list.
            int tries = 0;
            int itemCount = 0;
            while (tries == 0 || tries <= itemCount)
            {
                List<UsingDirectiveOrSpace> items = ImportReader.ReadImports(holder);
                if (items == null)
                {
                    return;
                }

                itemCount = items.Count;
                List<UsingDirective> imports;
                List<List<UsingDirective>> requiredOrderByGroups;
                ImportInspector.FlattenImportsAndDetermineOrderAndSpacing(
                    configuration, items, out imports, out requiredOrderByGroups);

                SpaceChange nextChange = ImportInspector.GetNextSpacingModification(requiredOrderByGroups, items);
                if (nextChange != null)
                {
                    IUsingDirective usingBeforeSpace = holder.Imports[nextChange.Index - 1];
                    if (nextChange.ShouldInsert)
                    {
                        using (WriteLockCookie.Create())
                        {
                            var newLineText = new StringBuffer("\r\n");

                            LeafElementBase newLine = TreeElementFactory.CreateLeafElement(
                                CSharpTokenType.NEW_LINE, newLineText, 0, newLineText.Length);
                            LowLevelModificationUtil.AddChildAfter(usingBeforeSpace, newLine);
                        }
                    }
                    else
                    {
                        var syb = usingBeforeSpace.NextSibling;
                        for (; syb != null && !(syb is IUsingDirective); syb = syb.NextSibling)
                        {
                            if (syb.NodeType == CSharpTokenType.NEW_LINE)
                            {
                                LowLevelModificationUtil.DeleteChild(syb);
                            }
                        }
                    }
                }
                else
                {
                    break;
                }

                tries += 1;
            }
        }
 /// <summary>
 /// Initializes a <see cref="BaseHighlighting"/>.
 /// </summary>
 /// <param name="typeAndNamespaceHolder">The file or namespace block that contains
 /// the import list being highlighted.</param>
 /// <param name="config">The configuration that was active when we determined that
 /// the import list does not match the requirements.</param>
 internal BaseHighlighting(
     ICSharpTypeAndNamespaceHolderDeclaration typeAndNamespaceHolder, OrderUsingsConfiguration config)
 {
     _config = config;
     _typeAndNamespaceHolder = typeAndNamespaceHolder;
 }
 /// <summary>
 /// Recursively walk namespace declaration blocks, cleaning any import lists they
 /// contain.
 /// </summary>
 /// <param name="namespaceDeclarationNodes">The namespace declaration blocks
 /// to check.</param>
 /// <param name="configuration">The configuration defining the correct order
 /// and spacing.</param>
 private void WalkNamespaceDeclarations(
     TreeNodeCollection<ICSharpNamespaceDeclaration> namespaceDeclarationNodes,
     OrderUsingsConfiguration configuration)
 {
     foreach (var ns in namespaceDeclarationNodes)
     {
         CleanUsings(ns, configuration);
         WalkNamespaceDeclarations(ns.NamespaceDeclarations, configuration);
     }
 }
 /// <summary>
 /// Fixes the order and spacing for the using blocks in a file or namespace declaration block.
 /// </summary>
 /// <param name="holder">The file or namespace declaration blocks to check.</param>
 /// <param name="configuration">The configuration defining the correct order
 /// and spacing.</param>
 private void CleanUsings(
     ICSharpTypeAndNamespaceHolderDeclaration holder, OrderUsingsConfiguration configuration)
 {
     Fixes.FixOrder(holder, configuration);
     Fixes.FixSpacing(holder, configuration);
 }