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

EduardSergeev / vscode-haskutil / 9630010233

23 Jun 2024 02:10AM UTC coverage: 97.326% (+1.3%) from 96.059%
9630010233

Pull #89

github

web-flow
Merge 42bd3df9c into 3479e6943
Pull Request #89: Sort imported element lists on `Organize imports`

280 of 297 branches covered (94.28%)

89 of 93 new or added lines in 3 files covered. (95.7%)

12 existing lines in 6 files now uncovered.

1274 of 1309 relevant lines covered (97.33%)

15.57 hits per line

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

97.5
/src/features/importProvider/importDeclaration.ts
1
import { Range, TextDocument } from "vscode";
1✔
2
import Configuration from "../../configuration";
1✔
3

1✔
4
export default class ImportDeclaration {
1✔
5
  private _before: string = '';
1✔
6
  private _importElements: string[] = [];
1✔
7
  private _importSeparators: string[] = [];
1✔
8
  private _after: string = '';
1✔
9
  qualified: string = " ";
1✔
10
  alias?: string;
1✔
11
  importList?: string;
1✔
12
  hidingList?: string;
1✔
13
  offset?: number;
1✔
14
  length?: number;
1✔
15

1✔
16
  constructor(
1✔
17
    public module: string,
95✔
18
    optional?: {
95✔
19
      qualified?: string,
95✔
20
      alias?: string,
95✔
21
      importList?: string,
95✔
22
      importElements?: string,
95✔
23
      hidingList?: string,
95✔
24
      offset?: number,
95✔
25
      length?: number
95✔
26
    }) {
95✔
27
    if (optional) {
95✔
28
      this.qualified = optional.qualified || "";
88!
29
      this.alias = optional.alias;
88✔
30
      this.importList = optional.importList;
88✔
31
      this.importElements = optional.importElements;
88✔
32
      this.hidingList = optional.hidingList;
88✔
33
      this.offset = optional.offset;
88✔
34
      this.length = optional.length;
88✔
35
    }
88✔
36
  }
95✔
37

1✔
38
  private get separator() {
1✔
39
    return ', '
2✔
40
  };
1✔
41

1✔
42
  public get importElements() {
1✔
43
    const separators = this._importSeparators.concat('');
28✔
44
    const list = this._importElements.flatMap((elem, i) => [elem, separators[i]]);
28✔
45
    return [this._before, ...list, this._after].join('');
28✔
46
  }
28✔
47

1✔
48
  public set importElements(elementsString: string) {
1✔
49
    const input = elementsString ?? '';
88✔
50
    const empty = /^\s*$/g;
88✔
51
    const before = /^\s*/g;
88✔
52
    const after = /\s*$/g;
88✔
53
    const separators = /(?<=\S)\s*,\s*(?=\S)/g;
88✔
54
    if (empty.test(input)) {
88✔
55
      const middle = input.length / 2;
50✔
56
      this._before = input.slice(0, middle);
50✔
57
      this._after = input.slice(middle)
50✔
58
    } else {
88✔
59
      this._before = input.match(before)[0];
38✔
60
      this._after = input.match(after)[0];
38✔
61
    }
38✔
62
    const matches = [...input.matchAll(separators)].map(m => [m.index, m[0]] as const);
88✔
63
    this._importSeparators = matches.map(m => m[1]);
88✔
64
    const indices = matches.map(m => [m[0], m[0] + m[1].length] as const);
88✔
65
    const starts = [this._before.length].concat(indices.map(ixs => ixs[1]));
88✔
66
    const ends = indices.map(ixs => ixs[0]).concat(input.length - this._after.length);
88✔
67
    this._importElements = starts.map((ix, i) => input.slice(ix, ends[i])).filter(e => e !== '');
88✔
68
  }
88✔
69

1✔
70
  public addImportElement(newElem: string) {
1✔
71
    let before = `(${this.importElements})`;
7✔
72
    if (!this.importList) {
7✔
73
      this.importList = " ()";
4✔
74
      before = "()";
4✔
75
    }
4✔
76

7✔
77
    let index = this._importElements.findIndex(oldElem => this.compareImportElements(newElem, oldElem) < 0);
7✔
78
    index = index === -1 ? this._importElements.length : index;
7✔
79
    if (this._importElements.length > 0) {
7✔
80
      if (index === this._importElements.length) {
2!
NEW
81
        this._importSeparators.push(this.separator);
×
82
      } else {
2✔
83
        this._importSeparators.splice(index, 0, this.separator);
2✔
84
      }
2✔
85
    }
2✔
86
    this._importElements.splice(index, 0, newElem);
7✔
87

7✔
88
    this.importList = this.importList.replace(before, `(${this.importElements})`);
7✔
89
  }
7✔
90

1✔
91
  public removeElement(elem: string) {
1✔
92
    const before = this.importElements;
5✔
93

5✔
94
    const index = this._importElements.findIndex(oldElem => oldElem === elem || oldElem.replace(' ', '') == `${elem}(..)`);
5✔
95
    if (index !== -1) {
5✔
96
      if (this._importElements.length > 1) {
5✔
97
        if (index === this._importElements.length - 1) {
5✔
98
          this._importSeparators.pop();
2✔
99
        } else {
5✔
100
          this._importSeparators.splice(index, 1);
3✔
101
        }
3✔
102
      }
5✔
103
      this._importElements.splice(index, 1);
5✔
104

5✔
105
      this.importList = this.importList.replace(before, this.importElements);
5✔
106
    }
5✔
107
  }
5✔
108

1✔
109
  public get importElementsSorted() {
1✔
110
    return [...this._importElements]
47✔
111
      .sort(this.compareImportElements)
47✔
112
      .every((elem, i) => this._importElements[i] === elem);
47✔
113
  }
47✔
114

1✔
115
  public sortImportElements() {
1✔
116
    if (this._importElements.length > 0) {
2✔
117
      const before = this.importElements;
2✔
118
      this._importElements.sort(this.compareImportElements);
2✔
119
      this.importList = this.importList.replace(before, this.importElements);
2✔
120
    }
2✔
121
  }  
1✔
122

1✔
123
  private compareImportElements(left: string, right: string) {
1✔
124
    const toSortable = (elem: string) => elem.replace('(', '~');
32✔
125
    if (Configuration.shouldplaceOperatorsAfterFunctions) {
32!
NEW
126
      left = toSortable(left);
×
NEW
127
      right = toSortable(right);
×
NEW
128
    }
×
129
    return left < right ? -1 : left > right ? 1 : 0;
32!
130
  }
32✔
131

1✔
132
  public get text() {
1✔
133
    return `import${this.qualified || ""}${this.module}${this.alias || ""}${this.importList || ""}${this.hidingList || ""}`;
52!
134
  }
52✔
135

1✔
136
  public getRange(document: TextDocument): Range {
1✔
137
    return new Range(
84✔
138
      document.positionAt(this.offset),
84✔
139
      document.positionAt(this.offset + this.length));
84✔
140
  }
84✔
141

1✔
142
  public static getImports(text: string): ImportDeclaration[] {
1✔
143
    const importPattern = /^import((?:\s+qualified\s+)|\s+)(\S+)(\s+as\s+(\S+))?(\s*?\(((?:(?:\(.*?\))|.|\r?\n)*?)\))?(\s+hiding\s+\(((?:(?:\(.*?\))|.|\r?\n)*?)\))?/gm;
38✔
144
    const imports = [];
38✔
145
    for (let match; match = importPattern.exec(text);) {
38✔
146
      imports.push(new ImportDeclaration(
88✔
147
        match[2],
88✔
148
        {
88✔
149
          qualified: match[1],
88✔
150
          alias: match[3],
88✔
151
          importList: match[5],
88✔
152
          importElements: match[6],
88✔
153
          hidingList: match[7],
88✔
154
          offset: match.index,
88✔
155
          length: match[0].length
88✔
156
        }));
88✔
157
    }
88✔
158
    return imports;
38✔
159
  }
38✔
160
}
1✔
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

© 2026 Coveralls, Inc