/// <summary> /// Checks an import list against the configured ordering and spacing. /// </summary> /// <param name="holder">The import list container - either a file, or a namespace /// declaration block.</param> /// <param name="highlights">If the import does not meet the configured requirements, /// we allocate a list containing a highlight describing the problem and return /// it via this argument. (We allocate the list on demand to avoid allocations /// in the happy path in which all the import lists are correctly ordered and /// spaced.)</param> private void CheckImports( ICSharpTypeAndNamespaceHolderDeclaration holder, ref List <HighlightingInfo> highlights) { List <UsingDirectiveOrSpace> items = ImportReader.ReadImports(holder); List <UsingDirective> imports; List <List <UsingDirective> > requiredOrderByGroups; ImportInspector.FlattenImportsAndDetermineOrderAndSpacing( _config, items, out imports, out requiredOrderByGroups); bool orderIsCorrect = true; if (requiredOrderByGroups != null) { Relocation nextChange = ImportInspector.GetNextUsingToMove(requiredOrderByGroups, imports); if (nextChange != null) { orderIsCorrect = false; AddHighlight(holder, ref highlights, new UsingOrderHighlighting(holder, _config)); } } // If (and only if) the order is correct, we go on to check the spacing. if (orderIsCorrect) { SpaceChange nextChange = ImportInspector.GetNextSpacingModification(requiredOrderByGroups, items); if (nextChange != null) { AddHighlight(holder, ref highlights, new UsingSpacingHighlighting(holder, _config)); } } }
/// <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> /// 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; } }