• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

b1f6c1c4 / ProfessionalAccounting / 320

16 Oct 2024 05:07PM UTC coverage: 55.799% (-1.1%) from 56.944%
320

push

appveyor

b1f6c1c4
final taobao

6264 of 11226 relevant lines covered (55.8%)

126.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.87
/AccountingServer.Shell/IShellComponent.cs
1
/* Copyright (C) 2020-2024 b1f6c1c4
2
 *
3
 * This file is part of ProfessionalAccounting.
4
 *
5
 * ProfessionalAccounting is free software: you can redistribute it and/or
6
 * modify it under the terms of the GNU Affero General Public License as
7
 * published by the Free Software Foundation, version 3.
8
 *
9
 * ProfessionalAccounting is distributed in the hope that it will be useful, but
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License
12
 * for more details.
13
 *
14
 * You should have received a copy of the GNU Affero General Public License
15
 * along with ProfessionalAccounting.  If not, see
16
 * <https://www.gnu.org/licenses/>.
17
 */
18

19
using System;
20
using System.Collections;
21
using System.Collections.Generic;
22
using System.Linq;
23

24
namespace AccountingServer.Shell;
25

26
/// <summary>
27
///     表达式解释组件
28
/// </summary>
29
internal interface IShellComponent
30
{
31
    /// <summary>
32
    ///     执行表达式
33
    /// </summary>
34
    /// <param name="expr">表达式</param>
35
    /// <param name="session">客户端会话</param>
36
    /// <returns>执行结果</returns>
37
    IAsyncEnumerable<string> Execute(string expr, Session session);
38

39
    /// <summary>
40
    ///     粗略判断表达式是否可执行
41
    /// </summary>
42
    /// <param name="expr">表达式</param>
43
    /// <returns>是否可执行</returns>
44
    bool IsExecutable(string expr);
45
}
46

47
/// <summary>
48
///     从委托创建表达式解释组件
49
/// </summary>
50
internal class ShellComponent : IShellComponent
51
{
52
    /// <summary>
53
    ///     操作
54
    /// </summary>
55
    private readonly Func<string, Session, IAsyncEnumerable<string>> m_Action;
56

57
    /// <summary>
58
    ///     首段字符串
59
    /// </summary>
60
    private readonly string m_Initial;
61

62
    public ShellComponent(string initial, Func<string, Session, IAsyncEnumerable<string>> action)
260✔
63
    {
260✔
64
        m_Initial = initial;
260✔
65
        m_Action = action;
260✔
66
    }
260✔
67

68
    /// <inheritdoc />
69
    public IAsyncEnumerable<string> Execute(string expr, Session session)
70
        => m_Action(m_Initial == null ? expr : expr.Rest(), session);
×
71

72
    /// <inheritdoc />
73
    public bool IsExecutable(string expr) => m_Initial == null || expr.Initial() == m_Initial;
×
74
}
75

76
/// <summary>
77
///     复合表达式解释组件
78
/// </summary>
79
internal sealed class ShellComposer : IShellComponent, IEnumerable
80
{
81
    private readonly List<IShellComponent> m_Components = new();
50✔
82

83
    /// <inheritdoc />
84
    public IEnumerator GetEnumerator() => m_Components.GetEnumerator();
×
85

86
    /// <inheritdoc />
87
    public IAsyncEnumerable<string> Execute(string expr, Session session)
88
        => FirstExecutable(expr).Execute(expr, session);
6✔
89

90
    /// <inheritdoc />
91
    public bool IsExecutable(string expr) => m_Components.Any(s => s.IsExecutable(expr));
×
92

93
    public void Add(IShellComponent shell) => m_Components.Add(shell);
330✔
94

95
    /// <summary>
96
    ///     第一个可以执行的组件
97
    /// </summary>
98
    /// <param name="expr">表达式</param>
99
    /// <returns>组件</returns>
100
    private IShellComponent FirstExecutable(string expr) =>
101
        m_Components.FirstOrDefault(s => s.IsExecutable(expr)) ?? throw new InvalidOperationException("表达式无效");
42✔
102
}
103

104
internal static class ExprHelper
105
{
106
    /// <summary>
107
    ///     首段字符串
108
    /// </summary>
109
    /// <param name="str">原字符串</param>
110
    /// <returns>首段</returns>
111
    public static string Initial(this string str)
112
    {
30✔
113
        if (str == null)
30✔
114
            return null;
×
115

116
        var id = str.IndexOfAny(new[] { ' ', '-' });
30✔
117
        return id < 0 ? str : str[..id];
30✔
118
    }
30✔
119

120
    /// <summary>
121
    ///     首段字符串
122
    /// </summary>
123
    /// <param name="str">原字符串</param>
124
    /// <returns>首段</returns>
125
    public static string Rest(this string str)
126
    {
×
127
        var id = str.IndexOfAny(new[] { ' ', '-' });
×
128
        return id < 0 ? "" : str[(id + 1)..].TrimStart();
×
129
    }
×
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc