diff --git a/BugReporter/GitHubUrlBuilder.cs b/BugReporter/GitHubUrlBuilder.cs index 8377bdab9ed..5b8b872a008 100644 --- a/BugReporter/GitHubUrlBuilder.cs +++ b/BugReporter/GitHubUrlBuilder.cs @@ -46,7 +46,7 @@ public GitHubUrlBuilder(IErrorReportUrlBuilder errorReportUrlBuilder) if (subject.Length > 69) { // if the subject is longer than 70 characters, trim it - subject = subject.Substring(0, 66) + "..."; + subject = subject[..66] + "..."; } string urlEncodedError = _errorReportUrlBuilder.Build(exception, exceptionInfo, environmentInfo, additionalInfo); diff --git a/Externals/NetSpell.SpellChecker/Dictionary/Affix/AffixUtility.cs b/Externals/NetSpell.SpellChecker/Dictionary/Affix/AffixUtility.cs index 19ecc1fc7ce..6f63d57b120 100644 --- a/Externals/NetSpell.SpellChecker/Dictionary/Affix/AffixUtility.cs +++ b/Externals/NetSpell.SpellChecker/Dictionary/Affix/AffixUtility.cs @@ -44,7 +44,7 @@ public static string AddPrefix(string word, AffixRule rule) if (passCount == entry.ConditionCount) { - string tempWord = word.Substring(entry.StripCharacters.Length); + string tempWord = word[entry.StripCharacters.Length..]; tempWord = entry.AddCharacters + tempWord; return tempWord; } @@ -94,7 +94,7 @@ public static string AddSuffix(string word, AffixRule rule) if (passCount == entry.ConditionCount) { int tempLen = word.Length - entry.StripCharacters.Length; - string tempWord = word.Substring(0, tempLen); + string tempWord = word[..tempLen]; tempWord += entry.AddCharacters; return tempWord; } @@ -253,7 +253,7 @@ public static string RemovePrefix(string word, AffixEntry entry) && word.StartsWith(entry.AddCharacters)) { // word with out affix - string tempWord = word.Substring(entry.AddCharacters.Length); + string tempWord = word[entry.AddCharacters.Length..]; // add back strip chars tempWord = entry.StripCharacters + tempWord; @@ -305,7 +305,7 @@ public static string RemoveSuffix(string word, AffixEntry entry) && word.EndsWith(entry.AddCharacters)) { // word with out affix - string tempWord = word.Substring(0, tempLength); + string tempWord = word[..tempLength]; // add back strip chars tempWord += entry.StripCharacters; diff --git a/Externals/NetSpell.SpellChecker/Dictionary/WordDictionary.cs b/Externals/NetSpell.SpellChecker/Dictionary/WordDictionary.cs index fb3df78f7d8..693557060da 100644 --- a/Externals/NetSpell.SpellChecker/Dictionary/WordDictionary.cs +++ b/Externals/NetSpell.SpellChecker/Dictionary/WordDictionary.cs @@ -582,7 +582,7 @@ public string PhoneticCode(string word) { if (rule.ReplaceMode) { - tempWord = rule.ReplaceString + tempWord.Substring(rule.ConditionCount - rule.ConsumeCount); + tempWord = rule.ReplaceString + tempWord[(rule.ConditionCount - rule.ConsumeCount)..]; } else { @@ -591,7 +591,7 @@ public string PhoneticCode(string word) code.Append(rule.ReplaceString); } - tempWord = tempWord.Substring(rule.ConditionCount - rule.ConsumeCount); + tempWord = tempWord[(rule.ConditionCount - rule.ConsumeCount)..]; } break; @@ -602,7 +602,7 @@ public string PhoneticCode(string word) // if no match consume one char if (prevWord.Length == tempWord.Length) { - tempWord = tempWord.Substring(1); + tempWord = tempWord[1..]; } } diff --git a/Externals/NetSpell.SpellChecker/Spelling.cs b/Externals/NetSpell.SpellChecker/Spelling.cs index de7cf44c2e0..6cee605a0f7 100644 --- a/Externals/NetSpell.SpellChecker/Spelling.cs +++ b/Externals/NetSpell.SpellChecker/Spelling.cs @@ -287,15 +287,13 @@ private void ReplaceChars(List tempSuggestion) for (int i = 0; i < replacementChars.Count; i++) { int split = replacementChars[i].IndexOf(' '); - string key = replacementChars[i].Substring(0, split); - string replacement = replacementChars[i].Substring(split + 1); + string key = replacementChars[i][..split]; + string replacement = replacementChars[i][(split + 1)..]; int pos = CurrentWord.IndexOf(key, StringComparison.InvariantCulture); while (pos > -1) { - string tempWord = CurrentWord.Substring(0, pos); - tempWord += replacement; - tempWord += CurrentWord.Substring(pos + key.Length); + string tempWord = $"{CurrentWord[..pos]}{replacement}{CurrentWord[(pos + key.Length)..]}"; if (FindWord(ref tempWord)) { @@ -403,8 +401,8 @@ private void TwoWords(List tempSuggestion) { for (int i = 1; i < CurrentWord.Length - 1; i++) { - string firstWord = CurrentWord.Substring(0, i); - string secondWord = CurrentWord.Substring(i); + string firstWord = CurrentWord[..i]; + string secondWord = CurrentWord[i..]; if (FindWord(ref firstWord) && FindWord(ref secondWord)) { @@ -747,8 +745,7 @@ public void ReplaceWord() // if first letter upper case, match case for replacement word if (char.IsUpper(_words[replacedIndex].ToString(), 0)) { - _replacementWord = _replacementWord.Substring(0, 1).ToUpper(CultureInfo.CurrentUICulture) - + _replacementWord.Substring(1); + _replacementWord = $"{char.ToUpper(_replacementWord[0], CultureInfo.CurrentUICulture)}{_replacementWord[1..]}"; } _text.Insert(index, _replacementWord); diff --git a/GitCommands/Config/ConfigFile.cs b/GitCommands/Config/ConfigFile.cs index faace9c8c5f..d49bb73df3e 100644 --- a/GitCommands/Config/ConfigFile.cs +++ b/GitCommands/Config/ConfigFile.cs @@ -107,8 +107,8 @@ private void SetStringValue(string setting, string value) { var keyIndex = FindAndCheckKeyIndex(setting); - var configSectionName = setting.Substring(0, keyIndex); - var keyName = setting.Substring(keyIndex + 1); + var configSectionName = setting[..keyIndex]; + var keyName = setting[(keyIndex + 1)..]; FindOrCreateConfigSection(configSectionName).SetValue(keyName, value); } @@ -149,8 +149,8 @@ public string GetValue(string setting, string defaultValue) var keyIndex = FindAndCheckKeyIndex(setting); - var configSectionName = setting.Substring(0, keyIndex); - var keyName = setting.Substring(keyIndex + 1); + var configSectionName = setting[..keyIndex]; + var keyName = setting[(keyIndex + 1)..]; var configSection = FindConfigSection(configSectionName); @@ -171,8 +171,8 @@ public IReadOnlyList GetValues(string setting) { var keyIndex = FindAndCheckKeyIndex(setting); - var configSectionName = setting.Substring(0, keyIndex); - var keyName = setting.Substring(keyIndex + 1); + var configSectionName = setting[..keyIndex]; + var keyName = setting[(keyIndex + 1)..]; var configSection = FindConfigSection(configSectionName); diff --git a/GitCommands/Config/ConfigSection.cs b/GitCommands/Config/ConfigSection.cs index 7ee77e1bd1b..e1571c3b9dd 100644 --- a/GitCommands/Config/ConfigSection.cs +++ b/GitCommands/Config/ConfigSection.cs @@ -26,7 +26,7 @@ internal ConfigSection(string name, bool forceCaseSensitive) if (slashIndex != -1) { // [section "subsection"] case sensitive - SectionName = name.Substring(0, slashIndex).Trim(); + SectionName = name[..slashIndex].Trim(); SubSection = name.Substring(slashIndex + 1, name.LastIndexOf('\"') - slashIndex - 1); SubSectionCaseSensitive = true; } @@ -46,8 +46,8 @@ internal ConfigSection(string name, bool forceCaseSensitive) throw new Exception("Invalid section name: " + name); } - SectionName = name.Substring(0, subSectionIndex).Trim(); - SubSection = name.Substring(subSectionIndex + 1).Trim(); + SectionName = name[..subSectionIndex].Trim(); + SubSection = name[(subSectionIndex + 1)..].Trim(); SubSectionCaseSensitive = false; } diff --git a/GitCommands/CustomDiffMergeToolCache.cs b/GitCommands/CustomDiffMergeToolCache.cs index 48bbd02c89c..7e43a389efd 100644 --- a/GitCommands/CustomDiffMergeToolCache.cs +++ b/GitCommands/CustomDiffMergeToolCache.cs @@ -116,7 +116,7 @@ private static IEnumerable ParseCustomDiffMergeTool(string output, strin // two tabs, then tool name, cmd (if split in 3) in second // cmd is unreliable for diff and not needed but could be used for mergetool special handling string[] delimit = { " ", ".cmd" }; - var tool = l.Substring(2).Split(delimit, 2, StringSplitOptions.None); + var tool = l[2..].Split(delimit, 2, StringSplitOptions.None); if (tool.Length == 0) { continue; diff --git a/GitCommands/Git/GitBranchNameNormaliser.cs b/GitCommands/Git/GitBranchNameNormaliser.cs index 4e7ff35449d..817bb313a0a 100644 --- a/GitCommands/Git/GitBranchNameNormaliser.cs +++ b/GitCommands/Git/GitBranchNameNormaliser.cs @@ -193,12 +193,12 @@ internal string Rule06(string branchName) branchName = Regex.Replace(branchName, @"(\/{2,})", "/"); if (branchName.StartsWith("/")) { - branchName = branchName.Substring(1); + branchName = branchName[1..]; } if (branchName.EndsWith("/")) { - branchName = branchName.Substring(0, branchName.Length - 1); + branchName = branchName[..^1]; } return branchName; diff --git a/GitCommands/Git/GitDescribeProvider.cs b/GitCommands/Git/GitDescribeProvider.cs index 8189d35eac4..f59a9e3a4c5 100644 --- a/GitCommands/Git/GitDescribeProvider.cs +++ b/GitCommands/Git/GitDescribeProvider.cs @@ -38,21 +38,21 @@ public GitDescribeProvider(Func getModule) return (description, string.Empty); } - string commitHash = description.Substring(commitHashPos + 2); + string commitHash = description[(commitHashPos + 2)..]; if (commitHash.Length == 0 || !revision.Equals(commitHash)) { return (description, string.Empty); } - description = description.Substring(0, commitHashPos); + description = description[..commitHashPos]; int commitCountPos = description.LastIndexOf("-", StringComparison.Ordinal); if (commitCountPos == -1) { return (description, string.Empty); } - string commitCount = description.Substring(commitCountPos + 1); - description = description.Substring(0, commitCountPos); + string commitCount = description[(commitCountPos + 1)..]; + description = description[..commitCountPos]; return (description, commitCount); IGitModule GetModule() diff --git a/GitCommands/Git/GitDirectoryResolver.cs b/GitCommands/Git/GitDirectoryResolver.cs index b38721ac30f..f4653eb60c7 100644 --- a/GitCommands/Git/GitDirectoryResolver.cs +++ b/GitCommands/Git/GitDirectoryResolver.cs @@ -79,7 +79,7 @@ public string Resolve(string repositoryPath) var line = _fileSystem.File.ReadLines(gitPath).FirstOrDefault(l => l.StartsWith(gitdir)); if (line is not null) { - string path = line.Substring(gitdir.Length).Trim().ToNativePath(); + string path = line[gitdir.Length..].Trim().ToNativePath(); if (Path.IsPathRooted(path)) { return path.EnsureTrailingPathSeparator(); diff --git a/GitCommands/Git/GitModule.cs b/GitCommands/Git/GitModule.cs index d8355a2f4b2..244fe97500a 100644 --- a/GitCommands/Git/GitModule.cs +++ b/GitCommands/Git/GitModule.cs @@ -117,11 +117,11 @@ public GitModule(string? workingDir) if (line.StartsWith(gitdir)) { - string gitPath = line.Substring(gitdir.Length).Trim(); + string gitPath = line[gitdir.Length..].Trim(); int pos = gitPath.IndexOf("/.git/modules/", StringComparison.Ordinal); if (pos != -1) { - gitPath = gitPath.Substring(0, pos + 1).Replace('/', '\\'); + gitPath = gitPath[..(pos + 1)].Replace('/', '\\'); gitPath = Path.GetFullPath(Path.Combine(WorkingDir, gitPath)); if (HasGitModulesFile(gitPath)) { @@ -134,7 +134,7 @@ public GitModule(string? workingDir) if (!string.IsNullOrEmpty(superprojectPath) && currentPath.ToPosixPath().StartsWith(superprojectPath.ToPosixPath())) { - var submodulePath = currentPath.Substring(superprojectPath.Length).ToPosixPath(); + var submodulePath = currentPath[superprojectPath.Length..].ToPosixPath(); ConfigFile configFile = new(Path.Combine(superprojectPath, ".gitmodules")); foreach (var configSection in configFile.ConfigSections) @@ -750,16 +750,16 @@ public async Task> GetConflictsAsync(string? filename = "") foreach (var line in unmerged) { int findSecondWhitespace = line.IndexOfAny(new[] { ' ', '\t' }); - string fileStage = findSecondWhitespace >= 0 ? line.Substring(findSecondWhitespace).Trim() : ""; + string fileStage = findSecondWhitespace >= 0 ? line[findSecondWhitespace..].Trim() : ""; findSecondWhitespace = fileStage.IndexOfAny(new[] { ' ', '\t' }); - string hash = findSecondWhitespace >= 0 ? fileStage.Substring(0, findSecondWhitespace).Trim() : ""; - fileStage = findSecondWhitespace >= 0 ? fileStage.Substring(findSecondWhitespace).Trim() : ""; + string hash = findSecondWhitespace >= 0 ? fileStage[..findSecondWhitespace].Trim() : ""; + fileStage = findSecondWhitespace >= 0 ? fileStage[findSecondWhitespace..].Trim() : ""; if (fileStage.Length > 2 && int.TryParse(fileStage[0].ToString(), out var stage) && stage is (>= 1 and <= 3)) { - var itemName = fileStage.Substring(2); + var itemName = fileStage[2..]; if (prevItemName != itemName && prevItemName is not null) { list.Add(new ConflictData(item[0], item[1], item[2])); @@ -1013,7 +1013,7 @@ public GitRevision GetRevision(ObjectId? objectId = null, bool shortFormat = fal ReadOnlySpan span = (body ?? "").AsSpan(); int endSubjectIndex = span.IndexOf('\n'); revision.Subject = endSubjectIndex >= 0 - ? span.Slice(0, endSubjectIndex).TrimEnd().ToString() + ? span[..endSubjectIndex].TrimEnd().ToString() : body ?? ""; } @@ -1203,7 +1203,7 @@ public ConfigFile GetSubmoduleConfigFile() Debug.Assert(WorkingDir.StartsWith(SuperprojectModule.WorkingDir), "Submodule working dir should start with super-project's working dir"); return Path.GetDirectoryName( - WorkingDir.Substring(SuperprojectModule.WorkingDir.Length)).ToPosixPath(); + WorkingDir[SuperprojectModule.WorkingDir.Length..]).ToPosixPath(); } public string GetSubmoduleFullPath(string? localPath) @@ -2239,7 +2239,7 @@ public IReadOnlyList GetRebasePatchFiles() if (value.IndexOf('<') > 0 && value.IndexOf('<') < value.Length) { var author = RFC2047Decoder.Parse(value); - patchFile.Author = author.Substring(0, author.IndexOf('<')).Trim(); + patchFile.Author = author[..author.IndexOf('<')].Trim(); } else { @@ -2250,7 +2250,7 @@ public IReadOnlyList GetRebasePatchFiles() case "Date": if (value.IndexOf('+') > 0 && value.IndexOf('<') < value.Length) { - patchFile.Date = value.Substring(0, value.IndexOf('+')).Trim(); + patchFile.Date = value[..value.IndexOf('+')].Trim(); } else { @@ -2299,7 +2299,7 @@ string AppendQuotedString(string str1, string str2) } Debug.Assert(m1.Groups[1].Value == m2.Groups[1].Value, "m1.Groups[1].Value == m2.Groups[1].Value"); - return str1.Substring(0, str1.Length - 2) + m2.Groups[2].Value + "?="; + return str1[..^2] + m2.Groups[2].Value + "?="; } } @@ -3081,7 +3081,7 @@ public static string GetSelectedBranchFast(string? repositoryPath, bool setDefau return string.Empty; } - return headFileContents.Substring(prefix.Length).TrimEnd(); + return headFileContents[prefix.Length..].TrimEnd(); } /// @@ -3324,7 +3324,7 @@ public IReadOnlyList GetAllBranchesWhichContainGivenCommit(ObjectId obje int idx = item.IndexOf(" ->", StringComparison.Ordinal); if (idx >= 0) { - item = item.Substring(0, idx); + item = item[..idx]; } } @@ -3578,7 +3578,7 @@ internal GitBlame ParseGitBlame(string output, Encoding encoding) else if (line.StartsWith("\t")) { // The contents of the actual line is output after the above header, prefixed by a TAB. This is to allow adding more header elements later. - var text = ReEncodeStringFromLossless(line.Substring(1), encoding); + var text = ReEncodeStringFromLossless(line[1..], encoding); GitBlameCommit commit; if (hasCommitHeader) @@ -3636,52 +3636,52 @@ internal GitBlame ParseGitBlame(string output, Encoding encoding) } else if (line.StartsWith("author ")) { - author = ReEncodeStringFromLossless(line.Substring("author ".Length)); + author = ReEncodeStringFromLossless(line["author ".Length..]); hasCommitHeader = true; } else if (line.StartsWith("author-mail ")) { - authorMail = ReEncodeStringFromLossless(line.Substring("author-mail ".Length)); + authorMail = ReEncodeStringFromLossless(line["author-mail ".Length..]); hasCommitHeader = true; } else if (line.StartsWith("author-time ")) { - authorTime = DateTimeUtils.ParseUnixTime(line.Substring("author-time ".Length)); + authorTime = DateTimeUtils.ParseUnixTime(line["author-time ".Length..]); hasCommitHeader = true; } else if (line.StartsWith("author-tz ")) { - authorTimeZone = line.Substring("author-tz ".Length); + authorTimeZone = line["author-tz ".Length..]; hasCommitHeader = true; } else if (line.StartsWith("committer ")) { - committer = ReEncodeStringFromLossless(line.Substring("committer ".Length)); + committer = ReEncodeStringFromLossless(line["committer ".Length..]); hasCommitHeader = true; } else if (line.StartsWith("committer-mail ")) { - committerMail = line.Substring("committer-mail ".Length); + committerMail = line["committer-mail ".Length..]; hasCommitHeader = true; } else if (line.StartsWith("committer-time ")) { - committerTime = DateTimeUtils.ParseUnixTime(line.Substring("committer-time ".Length)); + committerTime = DateTimeUtils.ParseUnixTime(line["committer-time ".Length..]); hasCommitHeader = true; } else if (line.StartsWith("committer-tz ")) { - committerTimeZone = line.Substring("committer-tz ".Length); + committerTimeZone = line["committer-tz ".Length..]; hasCommitHeader = true; } else if (line.StartsWith("summary ")) { - summary = ReEncodeStringFromLossless(line.Substring("summary ".Length)); + summary = ReEncodeStringFromLossless(line["summary ".Length..]); hasCommitHeader = true; } else if (line.StartsWith("filename ")) { - filename = ReEncodeFileNameFromLossless(line.Substring("filename ".Length)); + filename = ReEncodeFileNameFromLossless(line["filename ".Length..]); hasCommitHeader = true; } } @@ -4195,8 +4195,8 @@ public bool IsRunningGitProcess() string diff; if (p > 0) { - header = s.Substring(0, p); - diff = s.Substring(p); + header = s[..p]; + diff = s[p..]; } else { @@ -4207,8 +4207,8 @@ public bool IsRunningGitProcess() p = diff.IndexOf("@@"); if (p > 0) { - diffHeader = diff.Substring(0, p); - diffContent = diff.Substring(p); + diffHeader = diff[..p]; + diffContent = diff[p..]; } else { @@ -4229,7 +4229,7 @@ public override string ToString() public string? GetLocalTrackingBranchName(string remoteName, string branch) { - var branchName = remoteName.Length > 0 ? branch.Substring(remoteName.Length + 1) : branch; + var branchName = remoteName.Length > 0 ? branch[(remoteName.Length + 1)..] : branch; foreach (var section in LocalConfigFile.GetConfigSections()) { if (section.SectionName == "branch" && section.GetValue("remote") == remoteName) diff --git a/GitCommands/Git/GitRef.cs b/GitCommands/Git/GitRef.cs index 0be7fc0b5ed..1f394a5e36a 100644 --- a/GitCommands/Git/GitRef.cs +++ b/GitCommands/Git/GitRef.cs @@ -123,7 +123,7 @@ string ParseName() public bool IsOther => !IsHead && !IsRemote && !IsTag; - public string LocalName => IsRemote && Name.StartsWith($"{Remote}/") ? Name.Substring(Remote.Length + 1) : Name; + public string LocalName => IsRemote && Name.StartsWith($"{Remote}/") ? Name[(Remote.Length + 1)..] : Name; public string Remote { get; } diff --git a/GitCommands/Git/GitRefName.cs b/GitCommands/Git/GitRefName.cs index 441cecc9dd5..f0d97719271 100644 --- a/GitCommands/Git/GitRefName.cs +++ b/GitCommands/Git/GitRefName.cs @@ -89,7 +89,7 @@ public static string GetRemoteBranch(string refName) return string.Empty; } - return refName.Substring(1 + startBranch); + return refName[(1 + startBranch)..]; } [Pure] diff --git a/GitCommands/Git/GitVersion.cs b/GitCommands/Git/GitVersion.cs index cf5b4583c5f..5fe3b36dc83 100644 --- a/GitCommands/Git/GitVersion.cs +++ b/GitCommands/Git/GitVersion.cs @@ -89,7 +89,7 @@ string Fix() if (version.StartsWith(Prefix)) { - return version.Substring(Prefix.Length).Trim(); + return version[Prefix.Length..].Trim(); } return version.Trim(); diff --git a/GitCommands/Git/SubmoduleHelpers.cs b/GitCommands/Git/SubmoduleHelpers.cs index b4d32b92c9a..36b760ec7ec 100644 --- a/GitCommands/Git/SubmoduleHelpers.cs +++ b/GitCommands/Git/SubmoduleHelpers.cs @@ -94,7 +94,7 @@ public static class SubmoduleHelpers int pos = line.IndexOf(commitStr); if (pos >= 0) { - hash = line.Substring(pos + commitStr.Length); + hash = line[(pos + commitStr.Length)..]; } bool endsWithDirty = hash.EndsWith("-dirty"); diff --git a/GitCommands/Patches/PatchManager.cs b/GitCommands/Patches/PatchManager.cs index 81ec791ea90..62de43dbeef 100644 --- a/GitCommands/Patches/PatchManager.cs +++ b/GitCommands/Patches/PatchManager.cs @@ -67,7 +67,7 @@ private static string CorrectHeaderForNewFile(string header) { if (line.StartsWith("+++")) { - pppLine = "---" + line.Substring(3); + pppLine = "---" + line[3..]; } } @@ -219,8 +219,8 @@ private static byte[] GetPatchBytes(string header, string body, Encoding fileCon return null; } - header = text.Substring(0, patchPos); - string diff = text.Substring(patchPos - 1); + header = text[..patchPos]; + string diff = text[(patchPos - 1)..]; string[] chunks = diff.Split(new[] { "\n@@" }, StringSplitOptions.RemoveEmptyEntries); List selectedChunks = new(); @@ -318,7 +318,7 @@ public PatchLine Clone() public void SetOperation(string operationMark) { - Text = operationMark + Text.Substring(1); + Text = operationMark + Text[1..]; } } @@ -363,11 +363,11 @@ internal sealed class SubChunk { if (inPostPart) { - removePart = removePart.Combine("\n", " " + removedLine.Text.Substring(1)); + removePart = removePart.Combine("\n", " " + removedLine.Text[1..]); } else { - prePart = prePart.Combine("\n", " " + removedLine.Text.Substring(1)); + prePart = prePart.Combine("\n", " " + removedLine.Text[1..]); } addedCount++; @@ -389,11 +389,11 @@ internal sealed class SubChunk { if (inPostPart) { - postPart = postPart.Combine("\n", " " + addedLine.Text.Substring(1)); + postPart = postPart.Combine("\n", " " + addedLine.Text[1..]); } else { - prePart = prePart.Combine("\n", " " + addedLine.Text.Substring(1)); + prePart = prePart.Combine("\n", " " + addedLine.Text[1..]); } addedCount++; @@ -449,7 +449,7 @@ internal sealed class SubChunk { wereSelectedLines = true; inPostPart = true; - addPart = addPart.Combine("\n", "+" + removedLine.Text.Substring(1)); + addPart = addPart.Combine("\n", "+" + removedLine.Text[1..]); addedCount++; } } @@ -460,18 +460,18 @@ internal sealed class SubChunk { wereSelectedLines = true; inPostPart = true; - removePart = removePart.Combine("\n", "-" + addedLine.Text.Substring(1)); + removePart = removePart.Combine("\n", "-" + addedLine.Text[1..]); removedCount++; } else { if (inPostPart) { - postPart = postPart.Combine("\n", " " + addedLine.Text.Substring(1)); + postPart = postPart.Combine("\n", " " + addedLine.Text[1..]); } else { - prePart = prePart.Combine("\n", " " + addedLine.Text.Substring(1)); + prePart = prePart.Combine("\n", " " + addedLine.Text[1..]); } addedCount++; diff --git a/GitCommands/PathUtil.cs b/GitCommands/PathUtil.cs index 13703644ab0..126dca1f41e 100644 --- a/GitCommands/PathUtil.cs +++ b/GitCommands/PathUtil.cs @@ -76,7 +76,7 @@ public static class PathUtil (dirPath[^1] == NativeDirectorySeparatorChar || dirPath[^1] == PosixDirectorySeparatorChar)) { - return dirPath.Substring(0, dirPath.Length - 1); + return dirPath[..^1]; } return dirPath; @@ -124,7 +124,7 @@ public static string GetFileName(string fileName) var pos = fileName.LastIndexOfAny(pathSeparators); if (pos != -1) { - fileName = fileName.Substring(pos + 1); + fileName = fileName[(pos + 1)..]; } return fileName; @@ -338,12 +338,12 @@ public static string GetRepositoryName(string? repositoryUrl) if (path.EndsWith(standardRepositorySuffix)) { - path = path.Substring(0, path.Length - standardRepositorySuffix.Length); + path = path[..^standardRepositorySuffix.Length]; } if (path.Contains("\\") || path.Contains("/")) { - name = path.Substring(path.LastIndexOfAny(new[] { '\\', '/' }) + 1); + name = path[(path.LastIndexOfAny(new[] { '\\', '/' }) + 1)..]; } } diff --git a/GitCommands/RevisionReader.cs b/GitCommands/RevisionReader.cs index d0ced9953ab..571d8742797 100644 --- a/GitCommands/RevisionReader.cs +++ b/GitCommands/RevisionReader.cs @@ -218,10 +218,10 @@ private bool TryParseRevision(in ArraySegment chunk, [NotNullWhen(returnVa ReadOnlySpan array = chunk.AsSpan(); // The first 40 bytes are the revision ID and the tree ID back to back - if (!ObjectId.TryParseAsciiHexReadOnlySpan(array.Slice(0, ObjectId.Sha1CharCount), out var objectId) || + if (!ObjectId.TryParseAsciiHexReadOnlySpan(array[..ObjectId.Sha1CharCount], out var objectId) || !ObjectId.TryParseAsciiHexReadOnlySpan(array.Slice(ObjectId.Sha1CharCount, ObjectId.Sha1CharCount), out var treeId)) { - ParseAssert($"Log parse error, object id: {chunk.Count}({array.Slice(0, ObjectId.Sha1CharCount).ToString()}"); + ParseAssert($"Log parse error, object id: {chunk.Count}({array[..ObjectId.Sha1CharCount].ToString()}"); revision = default; return false; } @@ -421,7 +421,7 @@ public StringLineReader(in ReadOnlySpan s) int lengthSubject = bodySlice.IndexOf('\n'); bool hasMultiLineMessage = lengthSubject >= 0; string subject = hasMultiLineMessage - ? bodySlice.Slice(0, lengthSubject).TrimEnd().ToString() + ? bodySlice[..lengthSubject].TrimEnd().ToString() : bodySlice.ToString(); // See caller for reasoning when message body can be omitted diff --git a/GitCommands/Settings/AppSettings.cs b/GitCommands/Settings/AppSettings.cs index 81fc93f75e6..f37a455939d 100644 --- a/GitCommands/Settings/AppSettings.cs +++ b/GitCommands/Settings/AppSettings.cs @@ -223,11 +223,11 @@ public static void UsingContainer(DistributedSettings settingsContainer, Action int len = debugPath.Length; if (gitExtDir.Length > len) { - var path = gitExtDir.Substring(gitExtDir.Length - len); + var path = gitExtDir[^len..]; if (debugPath.ToPosixPath() == path.ToPosixPath()) { - string projectPath = gitExtDir.Substring(0, gitExtDir.Length - len); + string projectPath = gitExtDir[..^len]; return Path.Combine(projectPath, "Bin"); } } diff --git a/GitCommands/StringExtensions.cs b/GitCommands/StringExtensions.cs index 0812848060c..8531d541dba 100644 --- a/GitCommands/StringExtensions.cs +++ b/GitCommands/StringExtensions.cs @@ -19,7 +19,7 @@ public static class StringExtensions public static string RemovePrefix(this string str, string prefix, StringComparison comparison = StringComparison.Ordinal) { return str.StartsWith(prefix, comparison) - ? str.Substring(prefix.Length) + ? str[prefix.Length..] : str; } @@ -31,7 +31,7 @@ public static string RemovePrefix(this string str, string prefix, StringComparis public static string RemoveSuffix(this string str, string suffix, StringComparison comparison = StringComparison.Ordinal) { return str.EndsWith(suffix, comparison) - ? str.Substring(0, str.Length - suffix.Length) + ? str[..^suffix.Length] : str; } @@ -46,7 +46,7 @@ public static string SubstringUntil(this string str, char c) var index = str.IndexOf(c); return index != -1 - ? str.Substring(0, index) + ? str[..index] : str; } @@ -61,7 +61,7 @@ public static string SubstringUntilLast(this string str, char c) var index = str.LastIndexOf(c); return index != -1 - ? str.Substring(0, index) + ? str[..index] : str; } @@ -76,7 +76,7 @@ public static string SubstringAfter(this string str, char c) var index = str.IndexOf(c); return index != -1 - ? str.Substring(index + 1) + ? str[(index + 1)..] : str; } @@ -91,7 +91,7 @@ public static string SubstringAfter(this string str, string s, StringComparison var index = str.IndexOf(s, comparison); return index != -1 - ? str.Substring(index + s.Length) + ? str[(index + s.Length)..] : str; } @@ -106,7 +106,7 @@ public static string SubstringAfterLast(this string str, char c) var index = str.LastIndexOf(c); return index != -1 - ? str.Substring(index + 1) + ? str[(index + 1)..] : str; } @@ -121,7 +121,7 @@ public static string SubstringAfterLast(this string str, string s, StringCompari var index = str.LastIndexOf(s, comparison); return index != -1 - ? str.Substring(index + s.Length) + ? str[(index + s.Length)..] : str; } @@ -139,7 +139,7 @@ public static string CommonPrefix(this string? s, string? other) { if (s.Length <= prefixLength || s[prefixLength] != c) { - return s.Substring(0, prefixLength); + return s[..prefixLength]; } prefixLength++; @@ -221,7 +221,7 @@ public static bool StartsWithAny(this string? value, IEnumerable starts) if (value[^1] == '\n') { - value = value.Substring(0, value.Length - 1); + value = value[..^1]; } StringBuilder sb = new(capacity: value.Length); @@ -255,10 +255,10 @@ public static string ShortenTo(this string? str, int maxLength) if (maxLength < 3) { - return str.Substring(0, maxLength); + return str[..maxLength]; } - return str.Substring(0, maxLength - 3) + "..."; + return str[..(maxLength - 3)] + "..."; } /// diff --git a/GitCommands/Submodules/SubmoduleStatusProvider.cs b/GitCommands/Submodules/SubmoduleStatusProvider.cs index 03bd0119761..cc4497eb1f1 100644 --- a/GitCommands/Submodules/SubmoduleStatusProvider.cs +++ b/GitCommands/Submodules/SubmoduleStatusProvider.cs @@ -218,7 +218,7 @@ private static void SetSubmoduleData(GitModule currentModule, SubmoduleInfoResul var superWorkDir = currentModule.SuperprojectModule?.WorkingDir; var currentWorkDir = currentModule.WorkingDir; - var localPath = currentWorkDir.Substring(topProject.WorkingDir.Length); + var localPath = currentWorkDir[topProject.WorkingDir.Length..]; if (string.IsNullOrWhiteSpace(localPath)) { localPath = "."; diff --git a/GitCommands/UserRepositoryHistory/RecentRepoInfo.cs b/GitCommands/UserRepositoryHistory/RecentRepoInfo.cs index c952ca453a9..13c8b73d02c 100644 --- a/GitCommands/UserRepositoryHistory/RecentRepoInfo.cs +++ b/GitCommands/UserRepositoryHistory/RecentRepoInfo.cs @@ -153,7 +153,7 @@ private static void AddToOrderedSignDir(SortedList> // if there is no short name for a repo, then try to find unique caption extending short directory path if (shortenPath && repoInfo.DirInfo is not null) { - string s = repoInfo.DirName.Substring(repoInfo.DirInfo.FullName.Length); + string s = repoInfo.DirName[repoInfo.DirInfo.FullName.Length..]; if (!string.IsNullOrEmpty(s)) { s = s.Trim(Path.DirectorySeparatorChar); @@ -279,12 +279,12 @@ void ShortenPathWithCompany(int skipCount) if (company?.Length > skipCount) { - c = company.Substring(0, company.Length - skipCount); + c = company[..^skipCount]; } if (repository?.Length > skipCount) { - r = repository.Substring(skipCount, repository.Length - skipCount); + r = repository[skipCount..]; } repoInfo.Caption = MakePath(root, c!); @@ -315,7 +315,7 @@ bool ShortenPath(int skipCount) } else { - repoInfo.Caption = path.Substring(0, leftEnd) + ".." + path.Substring(rightStart, path.Length - rightStart); + repoInfo.Caption = path[..leftEnd] + ".." + path[rightStart..]; } return true; diff --git a/GitCommands/Utils/RFC2047Decoder.cs b/GitCommands/Utils/RFC2047Decoder.cs index 30950082076..826bee5ae81 100644 --- a/GitCommands/Utils/RFC2047Decoder.cs +++ b/GitCommands/Utils/RFC2047Decoder.cs @@ -86,7 +86,7 @@ private static string ParseEncodedWord(string input) } // Get the name of the encoding but skip the leading =? - string encodingName = input.Substring(2, input.IndexOf("?", 2, StringComparison.Ordinal) - 2); + string encodingName = input[2..input.IndexOf("?", 2, StringComparison.Ordinal)]; Encoding enc = Encoding.ASCII; if (!string.IsNullOrEmpty(encodingName)) { diff --git a/GitExtUtils/LazyStringSplit.cs b/GitExtUtils/LazyStringSplit.cs index 2a04edd592c..945f7541505 100644 --- a/GitExtUtils/LazyStringSplit.cs +++ b/GitExtUtils/LazyStringSplit.cs @@ -60,7 +60,7 @@ public bool MoveNext() if (delimiterIndex == -1) { - Current = _input.Substring(_index); + Current = _input[_index..]; _index = _input.Length + 1; return true; } diff --git a/GitUI/AutoCompletion/CommitAutoCompleteProvider.cs b/GitUI/AutoCompletion/CommitAutoCompleteProvider.cs index e72478d78b9..c8276567f3c 100644 --- a/GitUI/AutoCompletion/CommitAutoCompleteProvider.cs +++ b/GitUI/AutoCompletion/CommitAutoCompleteProvider.cs @@ -139,8 +139,8 @@ private static IEnumerable ReadOrInitializeAutoCompleteRegexes() foreach (var line in autoCompleteRegexes) { var i = line.IndexOf('='); - var extensionStr = line.Substring(0, i); - var regexStr = line.Substring(i + 1).Trim(); + var extensionStr = line[..i]; + var regexStr = line[(i + 1)..].Trim(); var extensions = extensionStr.LazySplit(',').Select(s => s.Trim()).Distinct(); Regex regex = new(regexStr, RegexOptions.Compiled); diff --git a/GitUI/Avatars/CustomAvatarProvider.cs b/GitUI/Avatars/CustomAvatarProvider.cs index aff38a2c1a0..5535d02f474 100644 --- a/GitUI/Avatars/CustomAvatarProvider.cs +++ b/GitUI/Avatars/CustomAvatarProvider.cs @@ -79,7 +79,7 @@ public static IAvatarProvider ParseTemplateString(string customProviderTemplates // and try to parse it as an AvatarProvider enum. if (providerTemplate.StartsWith("<") && providerTemplate.EndsWith(">")) { - var providerName = providerTemplate.Substring(1, providerTemplate.Length - 2); + var providerName = providerTemplate[1..^1]; if (Enum.TryParse(providerName, true, out var provider) && provider != AvatarProvider.Custom) diff --git a/GitUI/Avatars/TemplateFormatter.cs b/GitUI/Avatars/TemplateFormatter.cs index 5b6143d75db..787cf32845e 100644 --- a/GitUI/Avatars/TemplateFormatter.cs +++ b/GitUI/Avatars/TemplateFormatter.cs @@ -26,7 +26,7 @@ public static class TemplateFormatter var variableStartIndex = template.IndexOf('{', position); var fixIndex = variableStartIndex < 0 ? template.Length : variableStartIndex; - var fixValue = template.Substring(position, fixIndex - position); + var fixValue = template[position..fixIndex]; formatParts.Add((sb, _) => sb.Append(fixValue)); if (variableStartIndex < 0) diff --git a/GitUI/CommandsDialogs/BrowseDialog/DashboardControl/UserRepositoriesList.cs b/GitUI/CommandsDialogs/BrowseDialog/DashboardControl/UserRepositoriesList.cs index 0185c1b5000..19098f23011 100644 --- a/GitUI/CommandsDialogs/BrowseDialog/DashboardControl/UserRepositoriesList.cs +++ b/GitUI/CommandsDialogs/BrowseDialog/DashboardControl/UserRepositoriesList.cs @@ -492,7 +492,7 @@ private static string ShortenText(string text, Font font, float maxWidth) break; } - text = text.Substring(0, text.Length - 1); + text = text[..^1]; } return text + ellipsis; diff --git a/GitUI/CommandsDialogs/FormCheckoutBranch.cs b/GitUI/CommandsDialogs/FormCheckoutBranch.cs index 90fefc167b4..3a96f9e7029 100644 --- a/GitUI/CommandsDialogs/FormCheckoutBranch.cs +++ b/GitUI/CommandsDialogs/FormCheckoutBranch.cs @@ -460,7 +460,7 @@ private void Branches_SelectedIndexChanged(object sender, EventArgs e) { _remoteName = GitRefName.GetRemoteName(branch, Module.GetRemoteNames()); _localBranchName = Module.GetLocalTrackingBranchName(_remoteName, branch) ?? ""; - var remoteBranchName = _remoteName.Length > 0 ? branch.Substring(_remoteName.Length + 1) : branch; + var remoteBranchName = _remoteName.Length > 0 ? branch[(_remoteName.Length + 1)..] : branch; _newLocalBranchName = string.Concat(_remoteName, "_", remoteBranchName); int i = 2; while (LocalBranchExists(_newLocalBranchName)) diff --git a/GitUI/CommandsDialogs/FormCommit.cs b/GitUI/CommandsDialogs/FormCommit.cs index 8ee22871b4c..b2aed355682 100644 --- a/GitUI/CommandsDialogs/FormCommit.cs +++ b/GitUI/CommandsDialogs/FormCommit.cs @@ -2330,7 +2330,7 @@ void AddCommitMessageToMenu(string commitMessage) if (newlineIndex != -1) { - label = label.Substring(0, newlineIndex); + label = label[..newlineIndex]; } if (label.Length > maxLabelLength) @@ -2403,8 +2403,8 @@ private void generateListOfChangesInSubmodulesChangesToolStripMenuItem_Click(obj string diff = Module.GitExecutable.GetOutput(args); var lines = diff.Split(Delimiters.LineFeed, StringSplitOptions.RemoveEmptyEntries); const string subprojectCommit = "Subproject commit "; - var from = lines.Single(s => s.StartsWith("-" + subprojectCommit)).Substring(subprojectCommit.Length + 1); - var to = lines.Single(s => s.StartsWith("+" + subprojectCommit)).Substring(subprojectCommit.Length + 1); + var from = lines.Single(s => s.StartsWith("-" + subprojectCommit))[(subprojectCommit.Length + 1)..]; + var to = lines.Single(s => s.StartsWith("+" + subprojectCommit))[(subprojectCommit.Length + 1)..]; if (!string.IsNullOrEmpty(from) && !string.IsNullOrEmpty(to)) { sb.AppendLine("Submodule " + path + ":"); @@ -2424,7 +2424,7 @@ private void generateListOfChangesInSubmodulesChangesToolStripMenuItem_Click(obj } else { - sb.AppendLine(" * Revision changed to " + to.Substring(0, 7)); + sb.AppendLine(" * Revision changed to " + to[..7]); } sb.AppendLine(); diff --git a/GitUI/CommandsDialogs/FormPush.cs b/GitUI/CommandsDialogs/FormPush.cs index cb691ca03ea..9947b3f09ce 100644 --- a/GitUI/CommandsDialogs/FormPush.cs +++ b/GitUI/CommandsDialogs/FormPush.cs @@ -1016,7 +1016,7 @@ string CleanCommandOutput(string processOutput) return firstTabIdx == 40 ? processOutput : firstTabIdx > 40 - ? processOutput.Substring(firstTabIdx - 40) + ? processOutput[(firstTabIdx - 40)..] : string.Empty; } diff --git a/GitUI/CommandsDialogs/FormResolveConflicts.cs b/GitUI/CommandsDialogs/FormResolveConflicts.cs index 0e6a0bb3975..5cf603495a1 100644 --- a/GitUI/CommandsDialogs/FormResolveConflicts.cs +++ b/GitUI/CommandsDialogs/FormResolveConflicts.cs @@ -667,8 +667,8 @@ private bool InitMergetool() int idx = _mergetoolCmd.IndexOf(executablePattern); if (idx >= 0) { - _mergetoolPath = _mergetoolCmd.Substring(0, idx + executablePattern.Length + 1).Trim('\"', ' '); - _mergetoolCmd = _mergetoolCmd.Substring(idx + executablePattern.Length + 1); + _mergetoolPath = _mergetoolCmd[..(idx + executablePattern.Length + 1)].Trim('\"', ' '); + _mergetoolCmd = _mergetoolCmd[(idx + executablePattern.Length + 1)..]; } } diff --git a/GitUI/CommandsDialogs/FormVerify.LostObject.cs b/GitUI/CommandsDialogs/FormVerify.LostObject.cs index 7c301b7646e..efc5695cff2 100644 --- a/GitUI/CommandsDialogs/FormVerify.LostObject.cs +++ b/GitUI/CommandsDialogs/FormVerify.LostObject.cs @@ -134,7 +134,7 @@ private LostObject(LostObjectType objectType, string rawType, ObjectId objectId) else if (objectType == LostObjectType.Blob) { var hash = objectId.ToString(); - var blobPath = Path.Combine(module.WorkingDirGitDir, "objects", hash.Substring(0, 2), hash.Substring(2, ObjectId.Sha1CharCount - 2)); + var blobPath = Path.Combine(module.WorkingDirGitDir, "objects", hash[..2], hash[2..ObjectId.Sha1CharCount]); result.Date = new FileInfo(blobPath).CreationTime; } diff --git a/GitUI/CommandsDialogs/RevisionFileTreeControl.cs b/GitUI/CommandsDialogs/RevisionFileTreeControl.cs index b4463ab3346..cbe8a560a5d 100644 --- a/GitUI/CommandsDialogs/RevisionFileTreeControl.cs +++ b/GitUI/CommandsDialogs/RevisionFileTreeControl.cs @@ -960,7 +960,7 @@ public bool SelectFileOrFolder(string filePath) return false; } - return _revisionFileTreeController.SelectFileOrFolder(tvGitTree, filePath.Substring(Module.WorkingDir.Length)); + return _revisionFileTreeController.SelectFileOrFolder(tvGitTree, filePath[Module.WorkingDir.Length..]); } internal void RegisterGitHostingPluginInBlameControl() diff --git a/GitUI/CommandsDialogs/SubmodulesDialog/FormAddSubmodule.cs b/GitUI/CommandsDialogs/SubmodulesDialog/FormAddSubmodule.cs index d5b004b269e..f12e750cad4 100644 --- a/GitUI/CommandsDialogs/SubmodulesDialog/FormAddSubmodule.cs +++ b/GitUI/CommandsDialogs/SubmodulesDialog/FormAddSubmodule.cs @@ -104,7 +104,7 @@ private static IEnumerable LoadRemoteRepoBranches(IExecutable gitExecuta .Select(head => { int branchIndex = head.IndexOf(GitRefName.RefsHeadsPrefix); - return branchIndex == -1 ? null : head.Substring(branchIndex + GitRefName.RefsHeadsPrefix.Length); + return branchIndex == -1 ? null : head[(branchIndex + GitRefName.RefsHeadsPrefix.Length)..]; }) .WhereNotNull() .ToImmutableList(); diff --git a/GitUI/CommandsDialogs/WorktreeDialog/FormManageWorktree.cs b/GitUI/CommandsDialogs/WorktreeDialog/FormManageWorktree.cs index 1f010060036..a0811b5c15b 100644 --- a/GitUI/CommandsDialogs/WorktreeDialog/FormManageWorktree.cs +++ b/GitUI/CommandsDialogs/WorktreeDialog/FormManageWorktree.cs @@ -77,7 +77,7 @@ private void Initialize() var strings = line.Split(' '); if (strings[0] == "worktree") { - currentWorktree = new WorkTree { Path = Module.GetWindowsPath(line.Substring(9)) }; + currentWorktree = new WorkTree { Path = Module.GetWindowsPath(line[9..]) }; currentWorktree.IsDeleted = !Directory.Exists(currentWorktree.Path); _worktrees.Add(currentWorktree); } @@ -99,7 +99,7 @@ private void Initialize() currentWorktree.Branch = CleanBranchName(strings[1]); string? CleanBranchName(string? branch) - => branch != null && branch.StartsWith(GitRefName.RefsHeadsPrefix) ? branch.Substring(GitRefName.RefsHeadsPrefix.Length) : branch; + => branch != null && branch.StartsWith(GitRefName.RefsHeadsPrefix) ? branch[GitRefName.RefsHeadsPrefix.Length..] : branch; break; case "detached": diff --git a/GitUI/CommitInfo/CommitInfo.cs b/GitUI/CommitInfo/CommitInfo.cs index 8a055ea7f82..3703556d65b 100644 --- a/GitUI/CommitInfo/CommitInfo.cs +++ b/GitUI/CommitInfo/CommitInfo.cs @@ -244,7 +244,7 @@ private void ShowAll(string? what) int warningPos = tree.IndexOf("warning:"); if (warningPos >= 0) { - throw new RefsWarningException(tree.Substring(warningPos).LazySplit('\n', StringSplitOptions.RemoveEmptyEntries).First()); + throw new RefsWarningException(tree[warningPos..].LazySplit('\n', StringSplitOptions.RemoveEmptyEntries).First()); } int i = 0; diff --git a/GitUI/CommitInfo/RefsFormatter.cs b/GitUI/CommitInfo/RefsFormatter.cs index ef097550782..b439ba0b7ca 100644 --- a/GitUI/CommitInfo/RefsFormatter.cs +++ b/GitUI/CommitInfo/RefsFormatter.cs @@ -86,7 +86,7 @@ IEnumerable FormatTags(IEnumerable selectedTags) branchIsLocal = !branch.StartsWith(remotesPrefix); if (!branchIsLocal) { - noPrefixBranch = branch.Substring(remotesPrefix.Length); + noPrefixBranch = branch[remotesPrefix.Length..]; } } else diff --git a/GitUI/Editor/FileViewer.cs b/GitUI/Editor/FileViewer.cs index e60860fa9d3..33e1782ba7d 100644 --- a/GitUI/Editor/FileViewer.cs +++ b/GitUI/Editor/FileViewer.cs @@ -809,7 +809,7 @@ private void CopyNotStartingWith(char startChar) if (hpos <= pos) { char[] specials = { ' ', '-', '+' }; - lines = lines.Select(s => s.Length > 0 && specials.Any(c => c == s[0]) ? s.Substring(1) : s); + lines = lines.Select(s => s.Length > 0 && specials.Any(c => c == s[0]) ? s[1..] : s); } code = string.Join("\n", lines); @@ -1727,7 +1727,7 @@ string RemovePrefix(string line) foreach (var special in specials.Where(line.StartsWith)) { - return line.Substring(special.Length); + return line[special.Length..]; } return line; diff --git a/GitUI/Editor/RichTextBoxXhtmlSupportExtension.cs b/GitUI/Editor/RichTextBoxXhtmlSupportExtension.cs index 7337aefb21e..edb862654a1 100644 --- a/GitUI/Editor/RichTextBoxXhtmlSupportExtension.cs +++ b/GitUI/Editor/RichTextBoxXhtmlSupportExtension.cs @@ -690,13 +690,13 @@ public static string GetXHTMLText(this RichTextBox rtb, bool bParaFormat) for (int i = 0; i < colFormat.Count; i++) { var (pos, markup) = colFormat[i]; - strHTML.Append(WebUtility.HtmlEncode(strT.Substring(nAcum, pos - nAcum)) + markup); + strHTML.Append(WebUtility.HtmlEncode(strT[nAcum..pos]) + markup); nAcum = pos; } if (nAcum < strT.Length) { - strHTML.Append(strT.Substring(nAcum)); + strHTML.Append(strT[nAcum..]); } } catch (Exception /*ex*/) @@ -1157,8 +1157,8 @@ public static string GetPlainText(this RichTextBox rtb, int from, int to) // prior to net47 links were created via hidden text, and had the following format: "text#link" // extract the link portion only - string linkOldFormat = text.Substring(from, to - from); - return linkOldFormat.Substring(linkOldFormat.IndexOf(LinkSeparator) + LinkSeparator.Length); + string linkOldFormat = text[from..to]; + return linkOldFormat[(linkOldFormat.IndexOf(LinkSeparator) + LinkSeparator.Length)..]; } catch { @@ -1464,7 +1464,7 @@ private static void ProcessElement(XmlReader reader, RTFCurrentState cs, RichTex string text = reader.Value; if (text.StartsWith("#")) { - string strCr = text.Substring(1); + string strCr = text[1..]; int nCr = Convert.ToInt32(strCr, 16); Color color = Color.FromArgb(nCr); crFont = GetCOLORREF(color); @@ -1532,8 +1532,8 @@ private static void ProcessEndElement(XmlReader reader, RTFCurrentState cs, Rich int idx = rtfText.LastIndexOf('}'); if (idx != -1) { - string head = rtfText.Substring(0, idx); - string tail = rtfText.Substring(idx); + string head = rtfText[..idx]; + string tail = rtfText[idx..]; RtbSetSelectedRtf(rtb, $@"{head}\v {LinkSeparator}{cs.hyperlink}\v0{tail}"); length = rtb.TextLength - cs.hyperlinkStart; } diff --git a/GitUI/FindFilePredicateProvider.cs b/GitUI/FindFilePredicateProvider.cs index f72271963cc..2cf3a864cc0 100644 --- a/GitUI/FindFilePredicateProvider.cs +++ b/GitUI/FindFilePredicateProvider.cs @@ -30,7 +30,7 @@ public sealed class FindFilePredicateProvider : IFindFilePredicateProvider if (pattern.StartsWith(dir, StringComparison.OrdinalIgnoreCase)) { - pattern = pattern.Substring(dir.Length).TrimStart('/'); + pattern = pattern[dir.Length..].TrimStart('/'); return fileName => fileName?.StartsWith(pattern, StringComparison.OrdinalIgnoreCase) is true; } diff --git a/GitUI/LeftPanel/RemoteBranchNode.cs b/GitUI/LeftPanel/RemoteBranchNode.cs index 5413babfef9..dd914bea776 100644 --- a/GitUI/LeftPanel/RemoteBranchNode.cs +++ b/GitUI/LeftPanel/RemoteBranchNode.cs @@ -41,7 +41,7 @@ public bool Fetch() private RemoteBranchInfo GetRemoteBranchInfo() { var remote = FullPath.LazySplit('/').First(); - var branch = FullPath.Substring(remote.Length + 1); + var branch = FullPath[(remote.Length + 1)..]; return new RemoteBranchInfo(remote, branch); } diff --git a/GitUI/LeftPanel/SubmoduleTree.cs b/GitUI/LeftPanel/SubmoduleTree.cs index 14e029af064..73186220dd1 100644 --- a/GitUI/LeftPanel/SubmoduleTree.cs +++ b/GitUI/LeftPanel/SubmoduleTree.cs @@ -219,7 +219,7 @@ private void CreateSubmoduleNodes(SubmoduleInfoResult result, GitModule threadMo continue; } - string localPath = Path.GetDirectoryName(submoduleInfo.Path.Substring(superPath.Length)).ToPosixPath(); + string localPath = Path.GetDirectoryName(submoduleInfo.Path[superPath.Length..]).ToPosixPath(); var isCurrent = submoduleInfo.Bold; diff --git a/GitUI/Script/ScriptOptionsParser.cs b/GitUI/Script/ScriptOptionsParser.cs index 6e2ef7c4870..7db7813e46f 100644 --- a/GitUI/Script/ScriptOptionsParser.cs +++ b/GitUI/Script/ScriptOptionsParser.cs @@ -537,7 +537,7 @@ private static string StripRemoteName(string remoteBranchName) int firstSlashIndex = remoteBranchName.IndexOf('/'); if (firstSlashIndex >= 0) { - return remoteBranchName.Substring(firstSlashIndex + 1); + return remoteBranchName[(firstSlashIndex + 1)..]; } return remoteBranchName; diff --git a/GitUI/Theming/ThemeCssUrlResolver.cs b/GitUI/Theming/ThemeCssUrlResolver.cs index 9d113a5b182..2a64e5f247d 100644 --- a/GitUI/Theming/ThemeCssUrlResolver.cs +++ b/GitUI/Theming/ThemeCssUrlResolver.cs @@ -21,11 +21,11 @@ public string ResolveCssUrl(string url) { if (url.EndsWith(_themePathProvider.ThemeExtension, StringComparison.OrdinalIgnoreCase)) { - url = url.Substring(0, url.Length - _themePathProvider.ThemeExtension.Length); + url = url[..^_themePathProvider.ThemeExtension.Length]; } ThemeId id = url.StartsWith(CssVariableUserThemesDirectory) - ? new ThemeId(url.Substring(CssVariableUserThemesDirectory.Length), isBuiltin: false) + ? new ThemeId(url[CssVariableUserThemesDirectory.Length..], isBuiltin: false) : new ThemeId(url, isBuiltin: true); try diff --git a/GitUI/Theming/ThemeLoader.cs b/GitUI/Theming/ThemeLoader.cs index 35d7accedf9..c3ca6c1b9de 100644 --- a/GitUI/Theming/ThemeLoader.cs +++ b/GitUI/Theming/ThemeLoader.cs @@ -118,9 +118,7 @@ private static string[] GetClassNames(string themeFileName, StyleRule rule) throw StyleRuleThemeException(rule, themeFileName); } - return selectorText - .Substring(ClassSelector.Length) - .Split(new[] { ClassSelector }, StringSplitOptions.RemoveEmptyEntries); + return selectorText[ClassSelector.Length..].Split(new[] { ClassSelector }, StringSplitOptions.RemoveEmptyEntries); } private static Color GetColor(string themeFileName, StyleRule rule) diff --git a/GitUI/UserControls/ConsoleEmulatorOutputControl.cs b/GitUI/UserControls/ConsoleEmulatorOutputControl.cs index 239e9efb3a0..a3700923406 100644 --- a/GitUI/UserControls/ConsoleEmulatorOutputControl.cs +++ b/GitUI/UserControls/ConsoleEmulatorOutputControl.cs @@ -158,7 +158,7 @@ public ConsoleCommandLineOutputProcessor(int commandLineCharsInOutput, Action= 0 && slashIndex < name.Length) { - string path = name.Substring(0, slashIndex + 1); - string fileName = name.Substring(slashIndex + 1); + string path = name[..(slashIndex + 1)]; + string fileName = name[(slashIndex + 1)..]; return (path, fileName); } diff --git a/GitUI/UserControls/RevisionGrid/Columns/MessageColumnProvider.cs b/GitUI/UserControls/RevisionGrid/Columns/MessageColumnProvider.cs index e080588dd30..fb339b37d24 100644 --- a/GitUI/UserControls/RevisionGrid/Columns/MessageColumnProvider.cs +++ b/GitUI/UserControls/RevisionGrid/Columns/MessageColumnProvider.cs @@ -87,7 +87,7 @@ public override void OnCellPainting(DataGridViewCellPaintingEventArgs e, GitRevi e.State.HasFlag(DataGridViewElementStates.Selected), style.NormalFont, ref offset, - revision.ReflogSelector.Substring(5), + revision.ReflogSelector[5..], AppColor.OtherTag.GetThemeColor(), RefArrowType.None, messageBounds, diff --git a/GitUI/UserControls/RevisionGrid/FormQuickItemSelector.cs b/GitUI/UserControls/RevisionGrid/FormQuickItemSelector.cs index c5e805c1177..748c1c89427 100644 --- a/GitUI/UserControls/RevisionGrid/FormQuickItemSelector.cs +++ b/GitUI/UserControls/RevisionGrid/FormQuickItemSelector.cs @@ -43,7 +43,7 @@ protected void Init(IReadOnlyList items, string buttonText) // assume that the branch names or tags are never longer than MaxRefLength symbols long // if they are (sanity!) - don't resize past beyond certain limit - var label = item.Label.Length > MaxRefLength ? item.Label.Substring(0, MaxRefLength) : item.Label; + var label = item.Label.Length > MaxRefLength ? item.Label[..MaxRefLength] : item.Label; longestItemWidth = Math.Max(longestItemWidth, graphics.MeasureString(label, lbxRefs.Font).Width); } } diff --git a/GitUI/UserControls/RevisionGrid/QuickSearchProvider.cs b/GitUI/UserControls/RevisionGrid/QuickSearchProvider.cs index 24edc7e4e3b..065a8d48265 100644 --- a/GitUI/UserControls/RevisionGrid/QuickSearchProvider.cs +++ b/GitUI/UserControls/RevisionGrid/QuickSearchProvider.cs @@ -61,7 +61,7 @@ public void OnKeyPress(KeyPressEventArgs e) // backspace RestartQuickSearchTimer(); - _quickSearchString = _quickSearchString.Substring(0, _quickSearchString.Length - 1); + _quickSearchString = _quickSearchString[..^1]; FindNextMatch(curIndex, _quickSearchString, false); _lastQuickSearchString = _quickSearchString; diff --git a/Plugins/Bitbucket/GetPullRequest.cs b/Plugins/Bitbucket/GetPullRequest.cs index 7175fa52650..be2dbd2cb47 100644 --- a/Plugins/Bitbucket/GetPullRequest.cs +++ b/Plugins/Bitbucket/GetPullRequest.cs @@ -22,7 +22,7 @@ public static PullRequest Parse(JObject json) DestProjectKey = json["toRef"]["repository"]["project"]["key"].ToString(), DestRepo = json["toRef"]["repository"]["name"].ToString(), DestBranch = json["toRef"]["displayId"].ToString(), - CreatedDate = Convert.ToDouble(json["createdDate"].ToString().Substring(0, 10)) + CreatedDate = Convert.ToDouble(json["createdDate"].ToString()[..10]) }; var reviewers = json["reviewers"]; var participants = json["participants"]; diff --git a/Plugins/BuildServerIntegration/JenkinsIntegration/JenkinsAdapter.cs b/Plugins/BuildServerIntegration/JenkinsIntegration/JenkinsAdapter.cs index b8124012445..b3fe0d7c3e8 100644 --- a/Plugins/BuildServerIntegration/JenkinsIntegration/JenkinsAdapter.cs +++ b/Plugins/BuildServerIntegration/JenkinsIntegration/JenkinsAdapter.cs @@ -587,7 +587,7 @@ private static string FormatToGetJson(string restServicePath, bool buildsInfo = buildTree = post; } - restServicePath = restServicePath.Substring(0, postIndex); + restServicePath = restServicePath[..postIndex]; } else { diff --git a/Plugins/BuildServerIntegration/TeamCityIntegration/TeamCityAdapter.cs b/Plugins/BuildServerIntegration/TeamCityIntegration/TeamCityAdapter.cs index 9a6f30f9f56..bc34d9e6402 100644 --- a/Plugins/BuildServerIntegration/TeamCityIntegration/TeamCityAdapter.cs +++ b/Plugins/BuildServerIntegration/TeamCityIntegration/TeamCityAdapter.cs @@ -568,16 +568,16 @@ private Task GetFilteredBuildsXmlResponseAsync(string buildTypeId, Ca private static DateTime DecodeJsonDateTime(string dateTimeString) { - var dateTime = new DateTime( - int.Parse(dateTimeString.Substring(0, 4)), - int.Parse(dateTimeString.Substring(4, 2)), - int.Parse(dateTimeString.Substring(6, 2)), - int.Parse(dateTimeString.Substring(9, 2)), - int.Parse(dateTimeString.Substring(11, 2)), - int.Parse(dateTimeString.Substring(13, 2)), + DateTime dateTime = new DateTime( + int.Parse(dateTimeString.AsSpan(0, 4)), + int.Parse(dateTimeString.AsSpan(4, 2)), + int.Parse(dateTimeString.AsSpan(6, 2)), + int.Parse(dateTimeString.AsSpan(9, 2)), + int.Parse(dateTimeString.AsSpan(11, 2)), + int.Parse(dateTimeString.AsSpan(13, 2)), DateTimeKind.Utc) - .AddHours(int.Parse(dateTimeString.Substring(15, 3))) - .AddMinutes(int.Parse(dateTimeString.Substring(15, 1) + dateTimeString.Substring(18, 2))); + .AddHours(int.Parse(dateTimeString.AsSpan(15, 3))) + .AddMinutes(int.Parse(string.Concat(dateTimeString.AsSpan(15, 1), dateTimeString.AsSpan(18, 2)))); return dateTime; } diff --git a/Plugins/DeleteUnusedBranches/DeleteUnusedBranchesForm.cs b/Plugins/DeleteUnusedBranches/DeleteUnusedBranchesForm.cs index 57cd4bb1f7d..f51d5088e42 100644 --- a/Plugins/DeleteUnusedBranches/DeleteUnusedBranchesForm.cs +++ b/Plugins/DeleteUnusedBranches/DeleteUnusedBranchesForm.cs @@ -193,7 +193,7 @@ private void Delete_Click(object sender, EventArgs e) GitArgumentBuilder args = new("push") { remoteName, - $":{remoteBranch.Name.Substring(remoteBranchNameOffset)}" + $":{remoteBranch.Name[remoteBranchNameOffset..]}" }; _gitCommands.GitExecutable.GetOutput(args); } diff --git a/Plugins/GitFlow/GitFlowForm.cs b/Plugins/GitFlow/GitFlowForm.cs index 3af69a4a3c6..c55fc38d9da 100644 --- a/Plugins/GitFlow/GitFlowForm.cs +++ b/Plugins/GitFlow/GitFlowForm.cs @@ -113,7 +113,7 @@ private static bool TryExtractBranchFromHead(string currentRef, [NotNullWhen(ret if (currentRef.StartsWith(startRef)) { branchType = branch.ToString(); - branchName = currentRef.Substring(startRef.Length); + branchName = currentRef[startRef.Length..]; return true; } } diff --git a/Plugins/ReleaseNotesGenerator/HtmlFragment.cs b/Plugins/ReleaseNotesGenerator/HtmlFragment.cs index e955dc9e637..4cbfc77f82f 100644 --- a/Plugins/ReleaseNotesGenerator/HtmlFragment.cs +++ b/Plugins/ReleaseNotesGenerator/HtmlFragment.cs @@ -85,7 +85,7 @@ public HtmlFragment(string rawClipboardText) int endHtml = int.Parse(val); - Context = rawClipboardText.Substring(startHtml, endHtml - startHtml); + Context = rawClipboardText[startHtml..endHtml]; break; // Byte count from the beginning of the clipboard to the start of the fragment. @@ -106,7 +106,7 @@ public HtmlFragment(string rawClipboardText) } int endFragment = int.Parse(val); - Fragment = rawClipboardText.Substring(startFragment, endFragment - startFragment); + Fragment = rawClipboardText[startFragment..endFragment]; break; // Optional Source URL, used for resolving relative links. diff --git a/Plugins/Statistics/GitImpact/ImpactLoader.cs b/Plugins/Statistics/GitImpact/ImpactLoader.cs index a7e258faf31..2c127ba11dc 100644 --- a/Plugins/Statistics/GitImpact/ImpactLoader.cs +++ b/Plugins/Statistics/GitImpact/ImpactLoader.cs @@ -163,7 +163,7 @@ private void LoadModuleInfo(string command, IGitModule module, CancellationToken } // Strip "--- " - line = line.Substring(4); + line = line[4..]; // Split date and author string[] header = line.Split(new[] { " --- " }, 2, StringSplitOptions.RemoveEmptyEntries); diff --git a/ResourceManager/CommitDataRenders/CommitDataHeaderRenderer.cs b/ResourceManager/CommitDataRenders/CommitDataHeaderRenderer.cs index e173a3c712d..863e02fcff0 100644 --- a/ResourceManager/CommitDataRenders/CommitDataHeaderRenderer.cs +++ b/ResourceManager/CommitDataRenders/CommitDataHeaderRenderer.cs @@ -175,7 +175,7 @@ private static string GetEmail(string author) } ++ind; - return author.Substring(ind, author.LastIndexOf(">", StringComparison.Ordinal) - ind); + return author[ind..author.LastIndexOf(">", StringComparison.Ordinal)]; } private string RenderObjectIds(IEnumerable objectIds, bool showRevisionsAsLinks) diff --git a/ResourceManager/LinkFactory.cs b/ResourceManager/LinkFactory.cs index ba7e0e801a0..1942b856ccf 100644 --- a/ResourceManager/LinkFactory.cs +++ b/ResourceManager/LinkFactory.cs @@ -156,7 +156,7 @@ private static bool TryParseLink(string? linkUri, [NotNullWhen(returnValue: true break; } - uriCandidate = uriCandidate.Substring(idx + 1); + uriCandidate = uriCandidate[(idx + 1)..]; } return false; diff --git a/ResourceManager/Translator.cs b/ResourceManager/Translator.cs index e73eca27bfe..1b0f6e70249 100644 --- a/ResourceManager/Translator.cs +++ b/ResourceManager/Translator.cs @@ -25,7 +25,7 @@ public static class Translator var result = Directory.EnumerateFiles(translationsDir, translationName + "*.xlf"); foreach (var file in result) { - var name = Path.GetFileNameWithoutExtension(file).Substring(translationName.Length); + var name = Path.GetFileNameWithoutExtension(file)[translationName.Length..]; var t = TranslationSerializer.Deserialize(file) ?? new TranslationFile(); t.SourceLanguage = t.TranslationCategories.FirstOrDefault()?.SourceLanguage; diff --git a/UnitTests/GitCommands.Tests/AppTitleGeneratorTests.cs b/UnitTests/GitCommands.Tests/AppTitleGeneratorTests.cs index b5fb7f7ac1b..4bed765ede6 100644 --- a/UnitTests/GitCommands.Tests/AppTitleGeneratorTests.cs +++ b/UnitTests/GitCommands.Tests/AppTitleGeneratorTests.cs @@ -109,7 +109,7 @@ public void Generate_should_include_build_suffix() AppTitleGenerator.Initialise(buildSha, buildBranch); string title = _appTitleGenerator.Generate("a", true, null, defaultBranchName: _defaultBranchName); - title.Should().Be($"{MockRepositoryDescriptionProvider.ShortName} ({_defaultBranchName}) - {AppSettings.ApplicationName} {buildSha.Substring(0, 8)} ({buildBranch})"); + title.Should().Be($"{MockRepositoryDescriptionProvider.ShortName} ({_defaultBranchName}) - {AppSettings.ApplicationName} {buildSha[..8]} ({buildBranch})"); } #endif } diff --git a/UnitTests/GitCommands.Tests/Git/ObjectIdTests.cs b/UnitTests/GitCommands.Tests/Git/ObjectIdTests.cs index 59127ec1956..bfe512531b1 100644 --- a/UnitTests/GitCommands.Tests/Git/ObjectIdTests.cs +++ b/UnitTests/GitCommands.Tests/Git/ObjectIdTests.cs @@ -282,7 +282,7 @@ public void ToShortString() for (var length = 0; length < ObjectId.Sha1CharCount; length++) { - Assert.AreEqual(s.Substring(0, length), id.ToShortString(length)); + Assert.AreEqual(s[..length], id.ToShortString(length)); } Assert.Throws(() => id.ToShortString(-1)); diff --git a/UnitTests/GitUI.Tests/CommandsDialogs/FormOpenDirectoryTests.cs b/UnitTests/GitUI.Tests/CommandsDialogs/FormOpenDirectoryTests.cs index 0decc270db0..22792319559 100644 --- a/UnitTests/GitUI.Tests/CommandsDialogs/FormOpenDirectoryTests.cs +++ b/UnitTests/GitUI.Tests/CommandsDialogs/FormOpenDirectoryTests.cs @@ -54,7 +54,7 @@ public void OpenGitRepository_should_not_throw_if_path_not_end_with_slash() path[^1].Should().Be(Path.DirectorySeparatorChar); // ensure absence of the trailing slash isn't a problem - path = path.Substring(0, path.Length - 1); + path = path[..^1]; Assert.DoesNotThrow(() => FormOpenDirectory.TestAccessor.OpenGitRepository(path, _localRepositoryManager)); } diff --git a/UnitTests/GitUI.Tests/UserControls/ConsoleEmulatorOutputControlFixture.cs b/UnitTests/GitUI.Tests/UserControls/ConsoleEmulatorOutputControlFixture.cs index 6e020d2c454..be33a1e19fb 100644 --- a/UnitTests/GitUI.Tests/UserControls/ConsoleEmulatorOutputControlFixture.cs +++ b/UnitTests/GitUI.Tests/UserControls/ConsoleEmulatorOutputControlFixture.cs @@ -21,8 +21,8 @@ void FireDataReceived(TextEventArgs e) ConsoleCommandLineOutputProcessor filter = new(cmd.Length, FireDataReceived); - string chunk1 = cmd.Substring(0, 10); - string chunk2 = cmd.Substring(10, cmd.Length - 10) + Environment.NewLine + outputData; + string chunk1 = cmd[..10]; + string chunk2 = cmd[10..] + Environment.NewLine + outputData; filter.AnsiStreamChunkReceived(null, new AnsiStreamChunkEventArgs(GitModule.SystemEncoding.GetBytes(chunk1))); filter.AnsiStreamChunkReceived(null, new AnsiStreamChunkEventArgs(GitModule.SystemEncoding.GetBytes(chunk2))); @@ -43,8 +43,8 @@ void FireDataReceived(TextEventArgs e) ConsoleCommandLineOutputProcessor filter = new(cmd.Length, FireDataReceived); - string chunk1 = cmd.Substring(0, 10); - string chunk2 = cmd.Substring(10, cmd.Length - 10) + Environment.NewLine + outputData; + string chunk1 = cmd[..10]; + string chunk2 = cmd[10..] + Environment.NewLine + outputData; filter.AnsiStreamChunkReceived(null, new AnsiStreamChunkEventArgs(GitModule.SystemEncoding.GetBytes(chunk1))); filter.AnsiStreamChunkReceived(null, new AnsiStreamChunkEventArgs(GitModule.SystemEncoding.GetBytes(chunk2))); filter.Flush();