Esempio n. 1
0
        private void HandleIncludeDirective([NotNull] IT4Directive directive, [NotNull] CompositeElement parentElement)
        {
            var fileAttr = directive.GetAttribute(_directiveInfoManager.Include.FileAttribute.Name) as T4DirectiveAttribute;

            if (fileAttr == null)
            {
                return;
            }

            IT4Token valueToken = fileAttr.GetValueToken();

            if (valueToken == null)
            {
                return;
            }

            bool once = false;

            if (_t4Environment.VsVersion2.Major >= VsVersions.Vs2013)
            {
                string onceString = directive.GetAttributeValue(_directiveInfoManager.Include.OnceAttribute.Name);
                once = Boolean.TrueString.Equals(onceString, StringComparison.OrdinalIgnoreCase);
            }

            HandleInclude(valueToken.GetText(), fileAttr, parentElement, once);
        }
Esempio n. 2
0
        /// <summary>
        /// Adds a new directive after an existing one.
        /// </summary>
        /// <param name="directive">The directive to add.</param>
        /// <param name="anchor">The existing directive where <paramref name="directive"/> will be placed after.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirectiveAfter(IT4Directive directive, IT4Directive anchor)
        {
            if (directive == null)
            {
                throw new ArgumentNullException("directive");
            }
            if (anchor == null)
            {
                throw new ArgumentNullException("anchor");
            }

            using (this.CreateWriteLock()) {
                directive = ModificationUtil.AddChildAfter(anchor, directive);

                // if the directive was inserted between the anchor and a new line, add another new line before
                // the directive so that both directives have new lines after them
                ITreeNode sibling = directive.NextSibling;
                if (sibling is IT4Include)
                {
                    sibling = sibling.NextSibling;
                }
                if (sibling != null && sibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                {
                    ModificationUtil.AddChildBefore(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());
                }

                return(directive);
            }
        }
Esempio n. 3
0
        private void ProcessDirective([NotNull] IT4Directive directive)
        {
            IT4Token nameToken = directive.GetNameToken();

            if (nameToken == null)
            {
                return;
            }

            DirectiveInfo directiveInfo = _directiveInfoManager.GetDirectiveByName(nameToken.GetText());

            if (directiveInfo == null)
            {
                return;
            }

            IEnumerable <string> attributeNames = directive.GetAttributes().SelectNotNull(attr => attr.GetName());
            var hashSet = new JetHashSet <string>(attributeNames, StringComparer.OrdinalIgnoreCase);

            foreach (DirectiveAttributeInfo attributeInfo in directiveInfo.SupportedAttributes)
            {
                if (attributeInfo.IsRequired && !hashSet.Contains(attributeInfo.Name))
                {
                    AddHighlighting(new HighlightingInfo(nameToken.GetHighlightingRange(),
                                                         new MissingRequiredAttributeHighlighting(nameToken, attributeInfo.Name)));
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Removes a directive.
        /// </summary>
        /// <param name="directive">The directive to remove.</param>
        public void RemoveDirective(IT4Directive directive)
        {
            if (directive == null)
            {
                return;
            }

            using (this.CreateWriteLock()) {
                ITreeNode endNode = directive;

                // remove the included node with the include directive
                if (directive.IsSpecificDirective(Shell.Instance.GetComponent <DirectiveInfoManager>().Include))
                {
                    if (directive.NextSibling is IT4Include)
                    {
                        endNode = directive.NextSibling;
                    }
                }

                // remove the optional end line after the directive
                if (endNode.NextSibling != null && endNode.NextSibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                {
                    endNode = endNode.NextSibling;
                }

                ModificationUtil.DeleteChildRange(directive, endNode);
            }
        }
Esempio n. 5
0
        private void ProcessDirective([NotNull] IT4Directive directive)
        {
            IT4Token nameToken = directive.GetNameToken();

            if (nameToken == null)
            {
                return;
            }

            DirectiveInfo directiveInfo = _directiveInfoManager.GetDirectiveByName(nameToken.GetText());

            if (directiveInfo == null)
            {
                return;
            }

            // Notify of missing required attributes.
            IEnumerable <string> attributeNames = directive.GetAttributes().SelectNotNull(attr => attr.GetName());
            var hashSet = new JetHashSet <string>(attributeNames, StringComparer.OrdinalIgnoreCase);

            foreach (DirectiveAttributeInfo attributeInfo in directiveInfo.SupportedAttributes)
            {
                if (attributeInfo.IsRequired && !hashSet.Contains(attributeInfo.Name))
                {
                    AddHighlighting(new HighlightingInfo(nameToken.GetHighlightingRange(),
                                                         new MissingRequiredAttributeHighlighting(nameToken, attributeInfo.Name)));
                }
            }

            // Assembly attributes in preprocessed templates are useless.
            if (directiveInfo == _directiveInfoManager.Assembly && DaemonProcess.SourceFile.ToProjectFile().IsPreprocessedT4Template())
            {
                AddHighlighting(new HighlightingInfo(directive.GetHighlightingRange(), new IgnoredAssemblyDirectiveHighlighting(directive)));
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Handles a parameter directive, outputting an extra property.
        /// </summary>
        /// <param name="directive">The parameter directive.</param>
        private void HandleParameterDirective([NotNull] IT4Directive directive)
        {
            Pair <IT4Token, string> type = directive.GetAttributeValueIgnoreOnlyWhitespace(_directiveInfoManager.Parameter.TypeAttribute.Name);

            if (type.First == null || type.Second == null)
            {
                return;
            }

            Pair <IT4Token, string> name = directive.GetAttributeValueIgnoreOnlyWhitespace(_directiveInfoManager.Parameter.NameAttribute.Name);

            if (name.First == null || name.Second == null)
            {
                return;
            }

            StringBuilder builder = _parametersResult.Builder;

            builder.Append("[System.CodeDom.Compiler.GeneratedCodeAttribute] private global::");
            _parametersResult.AppendMapped(type.Second, type.First.GetTreeTextRange());
            builder.Append(' ');
            _parametersResult.AppendMapped(name.Second, name.First.GetTreeTextRange());
            builder.Append(" { get { return default(global::");
            builder.Append(type.Second);
            builder.AppendLine("); } }");
        }
Esempio n. 7
0
        private void ReportDuplicateDirective([NotNull] IT4Directive directive)
        {
            var warning          = new IgnoredDirectiveWarning(directive);
            var highlightingInfo = new HighlightingInfo(directive.GetHighlightingRange(), warning);

            MyHighlightings.Add(highlightingInfo);
        }
Esempio n. 8
0
 public override void VisitDirectiveNode(IT4Directive directiveParam, FoldingHighlightingConsumer context)
 {
     // It is necessary to determine offset like this
     // because using a <see cref="TreeNodeExtensions.GetDocumentStartOffset(ITreeNode)"/>
     // would yield incorrect results in some edge cases
     DirectiveFoldingStart ??= directiveParam.GetDocumentRange().StartOffset;
     DirectiveFoldingEnd = directiveParam.GetDocumentRange().EndOffset;
 }
Esempio n. 9
0
        public static IT4Token GetAttributeValueToken([CanBeNull] this IT4Directive directive, [CanBeNull] string attributeName)
        {
            if (String.IsNullOrEmpty(attributeName))
            {
                return(null);
            }

            return(directive?.GetAttribute(attributeName)?.GetValueToken());
        }
 public new static T4ImportWithLineDescription FromDirective([NotNull] IT4Directive directive)
 {
     (var source, string _) =
         directive.GetAttributeValueIgnoreOnlyWhitespace(T4DirectiveInfoManager.Import.NamespaceAttribute.Name);
     if (source == null)
     {
         return(null);
     }
     return(new T4ImportWithLineDescription(source));
 }
Esempio n. 11
0
        /// <summary>Handles a template directive, determining if we should output a Host property and use a base class.</summary>
        /// <param name="directive">The template directive.</param>
        private void HandleTemplateDirective([NotNull] IT4Directive directive)
        {
            string value = directive.GetAttributeValue(_directiveInfoManager.Template.HostSpecificAttribute.Name);

            _hasHost = Boolean.TrueString.Equals(value, StringComparison.OrdinalIgnoreCase);

            (IT4Token classNameToken, string className) = directive.GetAttributeValueIgnoreOnlyWhitespace(_directiveInfoManager.Template.InheritsAttribute.Name);
            if (classNameToken != null && className != null)
            {
                _inheritsResult.AppendMapped(className, classNameToken.GetTreeTextRange());
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Handles an import directive, equivalent of an using directive in C#.
        /// </summary>
        /// <param name="directive">The import directive.</param>
        private void HandleImportDirective([NotNull] IT4Directive directive)
        {
            Pair <IT4Token, string> ns = directive.GetAttributeValueIgnoreOnlyWhitespace(_directiveInfoManager.Import.NamespaceAttribute.Name);

            if (ns.First == null || ns.Second == null)
            {
                return;
            }

            _usingsResult.Builder.Append("using ");
            _usingsResult.AppendMapped(ns.Second, ns.First.GetTreeTextRange());
            _usingsResult.Builder.AppendLine(";");
        }
Esempio n. 13
0
        public static IT4Directive AddDirective([NotNull] this IT4File t4File, [NotNull] IT4Directive directive, [NotNull] DirectiveInfoManager directiveInfoManager)
        {
            Pair <IT4Directive, BeforeOrAfter> anchor = directive.FindAnchor(t4File.GetDirectives().ToArray(), directiveInfoManager);

            if (anchor.First == null)
            {
                return(t4File.AddDirective(directive));
            }

            return(anchor.Second == BeforeOrAfter.Before
                                ? t4File.AddDirectiveBefore(directive, anchor.First)
                                : t4File.AddDirectiveAfter(directive, anchor.First));
        }
Esempio n. 14
0
        /// <summary>Adds a new directive before an existing one.</summary>
        /// <param name="directive">The directive to add.</param>
        /// <param name="anchor">The existing directive where <paramref name="directive"/> will be placed before.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirectiveBefore(IT4Directive directive, IT4Directive anchor)
        {
            using (WriteLockCookie.Create(IsPhysical())) {
                directive = ModificationUtil.AddChildBefore(anchor, directive);

                // if the directive was inserted between a new line (or the file start) and the anchor, add another new line after
                // the directive so that both directives have new lines after them
                if (directive.PrevSibling == null || directive.PrevSibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                {
                    ModificationUtil.AddChildAfter(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());
                }

                return(directive);
            }
        }
Esempio n. 15
0
 public static IT4TreeNode GetAttributeValueToken(
     [CanBeNull] this IT4Directive directive,
     [CanBeNull] string attributeName
     )
 {
     if (string.IsNullOrEmpty(attributeName))
     {
         return(null);
     }
     return(directive
            ?.Attributes
            .Where(it => string.Equals(it.Name.GetText(), attributeName, StringComparison.OrdinalIgnoreCase))
            ?.FirstOrDefault()
            ?.Value);
 }
Esempio n. 16
0
 /// <summary>
 /// Handles a directive in the tree.
 /// </summary>
 /// <param name="directive">The directive.</param>
 private void HandleDirective([NotNull] IT4Directive directive)
 {
     if (directive.IsSpecificDirective(_directiveInfoManager.Import))
     {
         HandleImportDirective(directive);
     }
     else if (directive.IsSpecificDirective(_directiveInfoManager.Template))
     {
         HandleTemplateDirective(directive);
     }
     else if (directive.IsSpecificDirective(_directiveInfoManager.Parameter))
     {
         HandleParameterDirective(directive);
     }
 }
Esempio n. 17
0
        public static IT4Token GetAttributeValueToken([CanBeNull] this IT4Directive directive, [CanBeNull] string attributeName)
        {
            if (directive == null || String.IsNullOrEmpty(attributeName))
            {
                return(null);
            }

            IT4DirectiveAttribute attribute = directive.GetAttribute(attributeName);

            if (attribute == null)
            {
                return(null);
            }

            return(attribute.GetValueToken());
        }
Esempio n. 18
0
 private static string GetSortValue([NotNull] IT4Directive directive, [CanBeNull] DirectiveInfo directiveInfo,
                                    [NotNull] DirectiveInfoManager directiveInfoManager)
 {
     if (directiveInfo == directiveInfoManager.Assembly)
     {
         return(directive.GetAttributeValue(directiveInfoManager.Assembly.NameAttribute.Name));
     }
     if (directiveInfo == directiveInfoManager.Import)
     {
         return(directive.GetAttributeValue(directiveInfoManager.Import.NamespaceAttribute.Name));
     }
     if (directiveInfo == directiveInfoManager.Parameter)
     {
         return(directive.GetAttributeValue(directiveInfoManager.Parameter.NameAttribute.Name));
     }
     return(null);
 }
Esempio n. 19
0
        public static T4ParameterDescription FromDirective([NotNull] IT4Directive directive)
        {
            var    typeToken = directive.GetAttributeValueToken(T4DirectiveInfoManager.Parameter.TypeAttribute.Name);
            string typeText  = typeToken?.GetText();
            var    nameToken = directive.GetAttributeValueToken(T4DirectiveInfoManager.Parameter.NameAttribute.Name);
            string nameText  = nameToken?.GetText();

            if (string.IsNullOrEmpty(typeText))
            {
                return(null);
            }
            if (string.IsNullOrEmpty(nameText))
            {
                return(null);
            }
            return(new T4ParameterDescription(typeToken, nameToken, nameText));
        }
Esempio n. 20
0
        /// <summary>
        /// Adds a new directive.
        /// </summary>
        /// <param name="directive">The directive to add.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirective(IT4Directive directive)
        {
            if (directive == null)
                throw new ArgumentNullException("directive");

            IT4Directive anchor = GetDirectives().LastOrDefault();
            if (anchor != null)
                return AddDirectiveAfter(directive, anchor);

            using (this.CreateWriteLock()) {
                directive = FirstChild != null
                    ? ModificationUtil.AddChildBefore(FirstChild, directive)
                    : ModificationUtil.AddChild(this, directive);
                ModificationUtil.AddChildAfter(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());
                return directive;
            }
        }
Esempio n. 21
0
        /// <summary>Adds a new directive.</summary>
        /// <param name="directive">The directive to add.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirective(IT4Directive directive)
        {
            IT4Directive anchor = GetDirectives().LastOrDefault();

            if (anchor != null)
            {
                return(AddDirectiveAfter(directive, anchor));
            }

            using (WriteLockCookie.Create(IsPhysical())) {
                directive = FirstChild != null
                                        ? ModificationUtil.AddChildBefore(FirstChild, directive)
                                        : ModificationUtil.AddChild(this, directive);

                ModificationUtil.AddChildAfter(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());
                return(directive);
            }
        }
Esempio n. 22
0
        public static Pair <IT4Token, string> GetAttributeValueIgnoreOnlyWhitespace([CanBeNull] this IT4Directive directive, [CanBeNull] string attributeName)
        {
            IT4Token valueToken = directive.GetAttributeValueToken(attributeName);

            if (valueToken == null)
            {
                return(new Pair <IT4Token, string>());
            }

            string value = valueToken.GetText();

            if (value.Trim().Length == 0)
            {
                return(new Pair <IT4Token, string>());
            }

            return(new Pair <IT4Token, string>(valueToken, value));
        }
Esempio n. 23
0
        /// <summary>
        /// Handles an assembly directive.
        /// </summary>
        /// <param name="directive">The directive containing a potential assembly reference.</param>
        private void HandleAssemblyDirective([NotNull] IT4Directive directive)
        {
            string assemblyNameOrFile = directive.GetAttributeValue(_directiveInfoManager.Assembly.NameAttribute.Name);

            if (assemblyNameOrFile == null || (assemblyNameOrFile = assemblyNameOrFile.Trim()).Length == 0)
            {
                // Handle <#@ assembly name="" completion="someassembly" #>, which is a ForTea-specific way
                // to get completion for an implicit assembly (for example, added by a custom directive).
                assemblyNameOrFile = directive.GetAttributeValue("completion");
                if (assemblyNameOrFile == null || (assemblyNameOrFile = assemblyNameOrFile.Trim()).Length == 0)
                {
                    return;
                }
            }

            VsBuildMacroHelper.GetMacros(assemblyNameOrFile, _macros);
            _referencedAssemblies.Add(assemblyNameOrFile);
        }
Esempio n. 24
0
        private void HandleIncludeDirective([NotNull] IT4Directive directive, [NotNull] CompositeElement parentElement)
        {
            var fileAttr = (T4DirectiveAttribute)directive.GetAttribute(_directiveInfoManager.Include.FileAttribute.Name);

            if (fileAttr == null)
            {
                return;
            }

            IT4Token valueToken = fileAttr.GetValueToken();

            if (valueToken == null)
            {
                return;
            }

            HandleInclude(valueToken.GetText(), fileAttr, parentElement);
        }
Esempio n. 25
0
        private void AddDirective([NotNull] IT4File t4File, [NotNull] IT4Directive directive)
        {
            Pair <IT4Directive, BeforeOrAfter> anchor = directive.FindAnchor(t4File.GetDirectives().ToArray(), _directiveInfoManager);

            if (anchor.First != null)
            {
                if (anchor.Second == BeforeOrAfter.Before)
                {
                    t4File.AddDirectiveBefore(directive, anchor.First);
                }
                else
                {
                    t4File.AddDirectiveAfter(directive, anchor.First);
                }
            }
            else
            {
                t4File.AddDirective(directive);
            }
        }
Esempio n. 26
0
        /// <summary>Adds a new directive after an existing one.</summary>
        /// <param name="directive">The directive to add.</param>
        /// <param name="anchor">The existing directive where <paramref name="directive"/> will be placed after.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirectiveAfter(IT4Directive directive, IT4Directive anchor)
        {
            using (WriteLockCookie.Create(IsPhysical())) {
                directive = ModificationUtil.AddChildAfter(anchor, directive);

                // if the directive was inserted between the anchor and a new line, add another new line before
                // the directive so that both directives have new lines after them
                ITreeNode sibling = directive.NextSibling;
                if (sibling is IT4Include)
                {
                    sibling = sibling.NextSibling;
                }
                if (sibling != null && sibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                {
                    ModificationUtil.AddChildBefore(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());
                }

                return(directive);
            }
        }
Esempio n. 27
0
        private void ProcessDirective(IT4Directive directive)
        {
            switch (directive)
            {
            case IT4OutputDirective _ when !SeenOutputDirective:
                SeenOutputDirective = true;
                break;

            case IT4OutputDirective _:
                ReportDuplicateDirective(directive);
                break;

            case IT4TemplateDirective _ when !SeenTemplateDirective:
                SeenTemplateDirective = true;
                break;

            case IT4TemplateDirective _:
                ReportDuplicateDirective(directive);
                break;
            }
        }
Esempio n. 28
0
        public static Pair <IT4TreeNode, string> GetAttributeValueIgnoreOnlyWhitespace(
            [NotNull] this IT4Directive directive,
            [NotNull] string attributeName
            )
        {
            var valueToken = directive.GetAttributeValueToken(attributeName);

            if (valueToken == null)
            {
                return(new Pair <IT4TreeNode, string>());
            }

            string value = valueToken.GetText();

            if (value.IsNullOrWhitespace())
            {
                return(new Pair <IT4TreeNode, string>());
            }

            return(new Pair <IT4TreeNode, string>(valueToken, value));
        }
Esempio n. 29
0
        /// <summary>
        /// Adds a new directive.
        /// </summary>
        /// <param name="directive">The directive to add.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirective(IT4Directive directive)
        {
            if (directive == null)
            {
                throw new ArgumentNullException("directive");
            }

            IT4Directive anchor = GetDirectives().LastOrDefault();

            if (anchor != null)
            {
                return(AddDirectiveAfter(directive, anchor));
            }

            using (this.CreateWriteLock()) {
                directive = FirstChild != null
                                        ? ModificationUtil.AddChildBefore(FirstChild, directive)
                                        : ModificationUtil.AddChild(this, directive);

                ModificationUtil.AddChildAfter(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());
                return(directive);
            }
        }
Esempio n. 30
0
        /// <summary>
        /// Adds a new directive before an existing one.
        /// </summary>
        /// <param name="directive">The directive to add.</param>
        /// <param name="anchor">The existing directive where <paramref name="directive"/> will be placed before.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirectiveBefore(IT4Directive directive, IT4Directive anchor)
        {
            if (directive == null)
            {
                throw new ArgumentNullException("directive");
            }
            if (anchor == null)
            {
                throw new ArgumentNullException("anchor");
            }

            using (this.CreateWriteLock()) {
                directive = ModificationUtil.AddChildBefore(anchor, directive);

                // if the directive was inserted between a new line (or the file start) and the anchor, add another new line after
                // the directive so that both directives have new lines after them
                if (directive.PrevSibling == null || directive.PrevSibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                {
                    ModificationUtil.AddChildAfter(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());
                }

                return(directive);
            }
        }
Esempio n. 31
0
        /// <summary>
        /// Removes a directive.
        /// </summary>
        /// <param name="directive">The directive to remove.</param>
        public void RemoveDirective(IT4Directive directive)
        {
            if (directive == null)
                return;

            using (this.CreateWriteLock()) {
                ITreeNode endNode = directive;

                // remove the included node with the include directive
                if (directive.IsSpecificDirective(Shell.Instance.GetComponent<DirectiveInfoManager>().Include)) {
                    if (directive.NextSibling is IT4Include)
                        endNode = directive.NextSibling;
                }

                // remove the optional end line after the directive
                if (endNode.NextSibling != null && endNode.NextSibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                    endNode = endNode.NextSibling;

                ModificationUtil.DeleteChildRange(directive, endNode);
            }
        }
Esempio n. 32
0
        /// <summary>
        /// Adds a new directive before an existing one.
        /// </summary>
        /// <param name="directive">The directive to add.</param>
        /// <param name="anchor">The existing directive where <paramref name="directive"/> will be placed before.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirectiveBefore(IT4Directive directive, IT4Directive anchor)
        {
            if (directive == null)
                throw new ArgumentNullException("directive");
            if (anchor == null)
                throw new ArgumentNullException("anchor");

            using (this.CreateWriteLock()) {
                directive = ModificationUtil.AddChildBefore(anchor, directive);

                // if the directive was inserted between a new line (or the file start) and the anchor, add another new line after
                // the directive so that both directives have new lines after them
                if (directive.PrevSibling == null || directive.PrevSibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                    ModificationUtil.AddChildAfter(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());

                return directive;
            }
        }
Esempio n. 33
0
        /// <summary>
        /// Adds a new directive after an existing one.
        /// </summary>
        /// <param name="directive">The directive to add.</param>
        /// <param name="anchor">The existing directive where <paramref name="directive"/> will be placed after.</param>
        /// <returns>A new instance of <see cref="IT4Directive"/>, representing <paramref name="directive"/> in the T4 file.</returns>
        public IT4Directive AddDirectiveAfter(IT4Directive directive, IT4Directive anchor)
        {
            if (directive == null)
                throw new ArgumentNullException("directive");
            if (anchor == null)
                throw new ArgumentNullException("anchor");

            using (this.CreateWriteLock()) {
                directive = ModificationUtil.AddChildAfter(anchor, directive);

                // if the directive was inserted between the anchor and a new line, add another new line before
                // the directive so that both directives have new lines after them
                ITreeNode sibling = directive.NextSibling;
                if (sibling is IT4Include)
                    sibling = sibling.NextSibling;
                if (sibling != null && sibling.GetTokenType() == T4TokenNodeTypes.NewLine)
                    ModificationUtil.AddChildBefore(directive, T4TokenNodeTypes.NewLine.CreateLeafElement());

                return directive;
            }
        }
Esempio n. 34
0
        /// <summary>Finds an anchor for a newly created directive inside a list of existing directives.</summary>
        /// <param name="newDirective">The directive to add.</param>
        /// <param name="existingDirectives">The existing directives.</param>
        /// <param name="directiveInfoManager">An instance of <see cref="DirectiveInfoManager"/>.</param>
        /// <returns>A pair indicating the anchor (can be null) and its relative position.</returns>
        public static Pair <IT4Directive, BeforeOrAfter> FindAnchor(
            [NotNull] this IT4Directive newDirective,
            [NotNull] IT4Directive[] existingDirectives,
            [NotNull] DirectiveInfoManager directiveInfoManager
            )
        {
            // no anchor
            if (existingDirectives.Length == 0)
            {
                return(Pair.Of((IT4Directive)null, BeforeOrAfter.Before));
            }

            // directive name should never be null, but you never know
            string newName = newDirective.GetName();

            if (String.IsNullOrEmpty(newName))
            {
                return(Pair.Of(existingDirectives.Last(), BeforeOrAfter.After));
            }

            var           lastDirectiveByName = new Dictionary <string, IT4Directive>(StringComparer.OrdinalIgnoreCase);
            DirectiveInfo directiveInfo       = directiveInfoManager.GetDirectiveByName(newName);
            string        newsortValue        = GetSortValue(newDirective, directiveInfo, directiveInfoManager);

            foreach (IT4Directive existingDirective in existingDirectives)
            {
                string existingName = existingDirective.GetName();
                if (existingName == null)
                {
                    continue;
                }

                lastDirectiveByName[existingName] = existingDirective;

                // directive of the same type as the new one:
                // if the new directive comes alphabetically before the existing one, we got out anchor
                if (String.Equals(existingName, newName, StringComparison.OrdinalIgnoreCase))
                {
                    string existingSortValue = GetSortValue(existingDirective, directiveInfo, directiveInfoManager);
                    if (String.Compare(newsortValue, existingSortValue, StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        return(Pair.Of(existingDirective, BeforeOrAfter.Before));
                    }
                }
            }

            // no anchor being alphabetically after the new directive was found:
            // the last directive of the same type will be used as an anchor
            if (lastDirectiveByName.TryGetValue(newName, out IT4Directive lastDirective))
            {
                return(Pair.Of(lastDirective, BeforeOrAfter.After));
            }

            // there was no directive of the same type as the new one
            // the anchor will be the last directive of the type just before (determined by the position in DirectiveInfo.AllDirectives)
            if (directiveInfo != null)
            {
                int index = directiveInfoManager.AllDirectives.IndexOf(directiveInfo) - 1;
                while (index >= 0)
                {
                    if (lastDirectiveByName.TryGetValue(directiveInfoManager.AllDirectives[index].Name, out lastDirective))
                    {
                        return(Pair.Of(lastDirective, BeforeOrAfter.After));
                    }
                    --index;
                }
                return(Pair.Of(existingDirectives.First(), BeforeOrAfter.Before));
            }

            // we don't know the directive name (shouldn't happen), use the last directive as an anchor
            return(Pair.Of(existingDirectives.Last(), BeforeOrAfter.After));
        }