-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathMixedChecker.js
143 lines (136 loc) · 4.35 KB
/
MixedChecker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// LICENSE : MIT
"use strict";
import { analyze, isDearu, isDesumasu } from "analyze-desumasu-dearu";
export default class MixedChecker {
/**
* @param context
* @param {{preferDearu:boolean, preferDesumasu: boolean}} options
*/
constructor(context, options) {
this.context = context;
/**
* 明示的な優先するタイプの指定
* @type {{preferDearu: boolean, preferDesumasu: boolean, isStrict: boolean}}
*/
this.options = options;
this.dearuCount = 0;
this.desumasuCount = 0;
this.dearuHitList = [];
this.desumasuHitList = [];
this._queue = Promise.resolve();
}
check(node, text) {
this._queue = this._queue.then(() => {
const analyzeOptions = {
ignoreConjunction: !this.options.isStrict
};
return analyze(text, analyzeOptions).then(results => {
const retDearu = results.filter(isDearu);
const retDesumasu = results.filter(isDesumasu);
const dearuCount = this.dearuCount + retDearu.length;
const desumasuCount = this.desumasuCount + retDesumasu.length;
if (this.dearuCount !== dearuCount) {
this.dearuCount = dearuCount;
this.dearuHitList.push({
node,
matches: retDearu
});
}
if (this.desumasuCount !== desumasuCount) {
this.desumasuCount = desumasuCount;
this.desumasuHitList.push({
node,
matches: retDesumasu
});
}
});
});
}
/**
* @param {IgnoreManger}ignoreManger
* @returns {Promise.<TResult>}
*/
checkout(ignoreManger) {
return this._queue.then(() => {
if (!this.isOver()) {
return;
}
const RuleError = this.context.RuleError;
const report = this.context.report;
const overType = this.getOverType();
const overHitList = this.overHitList(overType);
// List
overHitList.forEach(({ node, matches }) => {
// Node
const lastHitNode = node;
// Tokens
matches.forEach(token => {
const hitIndex = node.range[0] + token.index;
if (ignoreManger.isIgnoredIndex(hitIndex)) {
return;
}
const ruleError = new RuleError(this.outputMessage(token), {
index: token.index
});
report(lastHitNode, ruleError);
});
});
});
}
isOver() {
return this.dearuCount !== 0 && this.desumasuCount !== 0;
}
/**
* 優先するtypeを返します。
* @returns {*}
*/
getOverType() {
if (this.options.preferDearu) {
return "である";
} else if (this.options.preferDesumasu) {
return "ですます";
}
if (this.dearuCount > this.desumasuCount) {
return "である";
} else {
return "ですます";
}
}
/**
* hist node list
* @param overType
* @returns {Array}
*/
overHitList(overType) {
if (overType === "である") {
return this.desumasuHitList;
} else if (overType === "ですます") {
return this.dearuHitList;
}
}
/**
* create message string
* @param token
* @returns {string}
*/
outputMessage(token) {
const overType = this.getOverType();
if (overType === "である") {
// である優先 => 最後の"ですます"を表示
return `"である"調 と "ですます"調 が混在
=> "${token.value}" がですます調
Total:
である : ${this.dearuCount}
ですます: ${this.desumasuCount}
`;
} else if (overType === "ですます") {
// ですます優先 => 最後の"である"を表示
return `"である"調 と "ですます"調 が混在
=> "${token.value}" がである調
Total:
である : ${this.dearuCount}
ですます: ${this.desumasuCount}
`;
}
}
}