<commit_before>﻿#region Using Directives

using System;
using System.Linq;
using System.Collections.Generic;
using Pharmatechnik.Nav.Language.Text;

#endregion

namespace Pharmatechnik.Nav.Language.CodeFixes {

    public sealed class RenameChoiceCodeFix: CodeFix {
        
        public RenameChoiceCodeFix(EditorSettings editorSettings, CodeGenerationUnit codeGenerationUnit, IChoiceNodeSymbol choiceNodeSymbol) : base(editorSettings, codeGenerationUnit) {
            ChoiceNodeSymbol = choiceNodeSymbol ?? throw new ArgumentNullException(nameof(choiceNodeSymbol));
        }

        public IChoiceNodeSymbol ChoiceNodeSymbol { get; }
        public ITaskDefinitionSymbol ContainingTask => ChoiceNodeSymbol.ContainingTask;

        public override bool CanApplyFix() {
            return true;
        }

        public string ValidateChoiceName(string choiceName) {

            choiceName = choiceName?.Trim();

            if (!SyntaxFacts.IsValidIdentifier(choiceName)) {
                return DiagnosticDescriptors.Semantic.Nav2000IdentifierExpected.MessageFormat;
            }

            var declaredNames = GetDeclaredNodeNames(ContainingTask);
            declaredNames.Remove(ChoiceNodeSymbol.Name); // Ist OK - pasiert halt nix

            if (declaredNames.Contains(choiceName)) {
                return String.Format(DiagnosticDescriptors.Semantic.Nav0022NodeWithName0AlreadyDeclared.MessageFormat, choiceName);
            }

            return null;
        }

        public IEnumerable<TextChange> GetTextChanges(string newChoiceName) {

            if (!CanApplyFix()) {
                throw new InvalidOperationException();
            }

            newChoiceName = newChoiceName?.Trim();

            var validationMessage = ValidateChoiceName(newChoiceName);
            if (!String.IsNullOrEmpty(validationMessage)) {
                throw new ArgumentException(validationMessage, nameof(newChoiceName));
            }

            // TODO Whitespace Kompensation

            var textChanges = new List<TextChange?>();
            // Die Choice Deklaration
            textChanges.Add(NewReplace(ChoiceNodeSymbol, newChoiceName));

            // Die Choice-Referenzen auf der "linken Seite"
            foreach (var transition in ChoiceNodeSymbol.Outgoings) {
                textChanges.Add(NewReplace(transition.Source, newChoiceName));
            }

            // Die Choice-Referenzen auf der "rechten Seite"
            foreach (var transition in ChoiceNodeSymbol.Incomings) {
                textChanges.Add(NewReplace(transition.Target, newChoiceName));
            }

            return textChanges.OfType<TextChange>().ToList();
        }
    }
}<commit_msg>Whitespace Handling<commit_after>﻿#region Using Directives

using System;
using System.Linq;
using System.Collections.Generic;
using Pharmatechnik.Nav.Language.Text;

#endregion

namespace Pharmatechnik.Nav.Language.CodeFixes {

    public sealed class RenameChoiceCodeFix: CodeFix {
        
        public RenameChoiceCodeFix(EditorSettings editorSettings, CodeGenerationUnit codeGenerationUnit, IChoiceNodeSymbol choiceNodeSymbol) : base(editorSettings, codeGenerationUnit) {
            ChoiceNodeSymbol = choiceNodeSymbol ?? throw new ArgumentNullException(nameof(choiceNodeSymbol));
        }

        public IChoiceNodeSymbol ChoiceNodeSymbol { get; }
        public ITaskDefinitionSymbol ContainingTask => ChoiceNodeSymbol.ContainingTask;

        public override bool CanApplyFix() {
            return true;
        }

        public string ValidateChoiceName(string choiceName) {

            choiceName = choiceName?.Trim();

            if (!SyntaxFacts.IsValidIdentifier(choiceName)) {
                return DiagnosticDescriptors.Semantic.Nav2000IdentifierExpected.MessageFormat;
            }

            var declaredNames = GetDeclaredNodeNames(ContainingTask);
            declaredNames.Remove(ChoiceNodeSymbol.Name); // Ist OK - pasiert halt nix

            if (declaredNames.Contains(choiceName)) {
                return String.Format(DiagnosticDescriptors.Semantic.Nav0022NodeWithName0AlreadyDeclared.MessageFormat, choiceName);
            }

            return null;
        }

        public IEnumerable<TextChange> GetTextChanges(string newChoiceName) {

            if (!CanApplyFix()) {
                throw new InvalidOperationException();
            }

            newChoiceName = newChoiceName?.Trim()??String.Empty;

            var validationMessage = ValidateChoiceName(newChoiceName);
            if (!String.IsNullOrEmpty(validationMessage)) {
                throw new ArgumentException(validationMessage, nameof(newChoiceName));
            }

            // TODO Whitespace Kompensation

            var textChanges = new List<TextChange?>();
            // Die Choice Deklaration
            textChanges.Add(NewReplace(ChoiceNodeSymbol, newChoiceName));

            // Die Choice-Referenzen auf der "linken Seite"
            foreach (var transition in ChoiceNodeSymbol.Outgoings) {
                if (transition.Source == null) {
                    continue;
                }

                // TODO Make pretty
                var oldSourceNode = transition.Source;
                var replaceExtent = oldSourceNode.Location.Extent;
                var replaceText   = newChoiceName;
                if (transition.EdgeMode != null) {
                    // Find teh First non-Whitespace Token after Source Edge
                    var firstNonWSpaceToken = transition.Syntax.SyntaxTree
                                                        .Tokens[TextExtent.FromBounds(oldSourceNode.End, transition.EdgeMode.End)]
                                                        .SkipWhile(token => token.Type==SyntaxTokenType.Whitespace).FirstOrDefault();
         
                    if (!firstNonWSpaceToken.IsMissing) {
                        
                        var availableSpace = oldSourceNode.Location.Length+ColumnsBetweenLocations(oldSourceNode.Location, firstNonWSpaceToken.GetLocation());

                        replaceExtent = TextExtent.FromBounds(oldSourceNode.Location.Start, firstNonWSpaceToken.Start);

                        var spaces = Math.Max(1, availableSpace - newChoiceName.Length);

                        replaceText = newChoiceName + new string(' ', spaces);
                    }
                }
                                
                textChanges.Add(new TextChange(replaceExtent, replaceText));
            }

            // Die Choice-Referenzen auf der "rechten Seite"
            foreach (var transition in ChoiceNodeSymbol.Incomings) {
                textChanges.Add(NewReplace(transition.Target, newChoiceName));
            }

            return textChanges.OfType<TextChange>().ToList();
        }
    }
}
{'fraction_non_alphanumeric': 0.07537762135210442, 'fraction_numerical': 0.002786332306789852, 'mean_word_length': 2.1943793911007026, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2264267', 'n_tokens_mistral': 1656, 'n_tokens_neox': 1574, 'n_words': 321}