code-gauge 2.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -106
- package/dist/cli.cjs +3 -3
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/cliConfig.cjs +1 -1
- package/dist/cliConfig.cjs.map +1 -1
- package/dist/cliConfig.d.ts +27 -84
- package/dist/cliConfig.js +1 -1
- package/dist/cliConfig.js.map +1 -1
- package/dist/crossFileDuplication.cjs +1 -1
- package/dist/crossFileDuplication.cjs.map +1 -1
- package/dist/crossFileDuplication.d.ts +9 -0
- package/dist/crossFileDuplication.js +1 -1
- package/dist/crossFileDuplication.js.map +1 -1
- package/dist/depDegree.cjs +2 -0
- package/dist/depDegree.cjs.map +1 -0
- package/dist/depDegree.d.ts +12 -0
- package/dist/depDegree.js +2 -0
- package/dist/depDegree.js.map +1 -0
- package/dist/diffCommand.cjs +5 -0
- package/dist/diffCommand.cjs.map +1 -0
- package/dist/diffCommand.d.ts +17 -0
- package/dist/diffCommand.js +5 -0
- package/dist/diffCommand.js.map +1 -0
- package/dist/duplication.cjs +1 -1
- package/dist/duplication.cjs.map +1 -1
- package/dist/duplication.d.ts +23 -2
- package/dist/duplication.js +1 -1
- package/dist/duplication.js.map +1 -1
- package/dist/git.cjs +2 -0
- package/dist/git.cjs.map +1 -0
- package/dist/git.d.ts +27 -0
- package/dist/git.js +2 -0
- package/dist/git.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -1
- package/dist/languages.cjs +1 -1
- package/dist/languages.cjs.map +1 -1
- package/dist/languages.js +1 -1
- package/dist/languages.js.map +1 -1
- package/dist/metrics.cjs +1 -2
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.ts +11 -0
- package/dist/metrics.js +1 -2
- package/dist/metrics.js.map +1 -1
- package/dist/nativeMetrics.cjs +1 -1
- package/dist/nativeMetrics.cjs.map +1 -1
- package/dist/nativeMetrics.d.ts +7 -3
- package/dist/nativeMetrics.js +1 -1
- package/dist/nativeMetrics.js.map +1 -1
- package/dist/regressionGate.cjs +2 -0
- package/dist/regressionGate.cjs.map +1 -0
- package/dist/regressionGate.d.ts +106 -0
- package/dist/regressionGate.js +2 -0
- package/dist/regressionGate.js.map +1 -0
- package/dist/scan.cjs +2 -0
- package/dist/scan.cjs.map +1 -0
- package/dist/scan.d.ts +55 -0
- package/dist/scan.js +2 -0
- package/dist/scan.js.map +1 -0
- package/dist/types.d.ts +24 -76
- package/package.json +7 -5
- package/dist/architectureMetrics.cjs +0 -2
- package/dist/architectureMetrics.cjs.map +0 -1
- package/dist/architectureMetrics.d.ts +0 -41
- package/dist/architectureMetrics.js +0 -2
- package/dist/architectureMetrics.js.map +0 -1
- package/dist/typescriptProject.cjs +0 -3
- package/dist/typescriptProject.cjs.map +0 -1
- package/dist/typescriptProject.d.ts +0 -24
- package/dist/typescriptProject.js +0 -3
- package/dist/typescriptProject.js.map +0 -1
package/dist/duplication.d.ts
CHANGED
|
@@ -89,6 +89,12 @@ export interface CrossFileDuplicationFileData {
|
|
|
89
89
|
candidates: CrossFileDuplicateCandidate[];
|
|
90
90
|
tokens: Token[];
|
|
91
91
|
containerStatements: TokenRange[][];
|
|
92
|
+
/**
|
|
93
|
+
* 1-based lines that are neither blank nor comment-only, so cross-file line coverage counts only
|
|
94
|
+
* code lines (blank rows inside multi-row tokens such as template literals carry no content).
|
|
95
|
+
* Optional for backward compatibility; without it, every matched-token row counts.
|
|
96
|
+
*/
|
|
97
|
+
codeLineNumbers?: Set<number>;
|
|
92
98
|
}
|
|
93
99
|
/**
|
|
94
100
|
* Detects copy-pasted regions within a file. Regions are compared by their normalized token
|
|
@@ -137,6 +143,16 @@ export interface ContextualSequenceCandidate {
|
|
|
137
143
|
* project-level selection with unusable single-file groups.
|
|
138
144
|
*/
|
|
139
145
|
export declare function collectSequenceWindowCandidates(contexts: SequenceWindowContext[], minTokens: number, requireMultipleContexts: boolean): ContextualSequenceCandidate[];
|
|
146
|
+
/**
|
|
147
|
+
* Longest-common-subsequence LENGTH of two symbol sequences via the Allison–Dix bit-parallel
|
|
148
|
+
* recurrence (O(|a|/32 · |b|) words): per symbol of `b`, `x = match | v` and
|
|
149
|
+
* `v = x & ~(x - ((v << 1) | 1))` over multi-word bit vectors; the set bits of `v` count the LCS.
|
|
150
|
+
* Only the length is needed (similarity is a ratio), and LCS length is algorithm-independent, so
|
|
151
|
+
* the native backend may use a different word size and still agree bit-for-bit.
|
|
152
|
+
*/
|
|
153
|
+
export declare function lcsLength(a: Int32Array, b: Int32Array): number;
|
|
154
|
+
/** djb2-style hash; XOR keeps the value in signed 32-bit range, which is fine for a grouping key. */
|
|
155
|
+
export declare function hashText(text: string): number;
|
|
140
156
|
/**
|
|
141
157
|
* Merges duplicate groups separated by a small token gap into one gapped (Type-3) clone group: a
|
|
142
158
|
* copy edited in one spot splits into two exact groups whose occurrences sit side by side in the
|
|
@@ -158,8 +174,8 @@ export declare function mergeAdjacentGroups<T extends CountedOccurrence>(groups:
|
|
|
158
174
|
/**
|
|
159
175
|
* Redundant copies one group adds to duplicateBlockCount. Each redundant occurrence contributes
|
|
160
176
|
* one count per matched fragment, so merging a gapped clone's fragments into one group does not
|
|
161
|
-
* halve
|
|
162
|
-
*
|
|
177
|
+
* halve duplicateBlockCount: an edited two-fragment pair still counts 2, exactly as its unmerged
|
|
178
|
+
* fragments did. Occurrence shapes can differ within one group (a
|
|
163
179
|
* gap-merged exact pair plus an appended whole-block near-miss copy), so every occurrence's
|
|
164
180
|
* fragments are summed and one representative — the largest — is deducted, keeping the count
|
|
165
181
|
* independent of source order. Occurrences a partial gapped merge also paired into a merged group
|
|
@@ -168,4 +184,9 @@ export declare function mergeAdjacentGroups<T extends CountedOccurrence>(groups:
|
|
|
168
184
|
* content — so no token span contributes to the count twice.
|
|
169
185
|
*/
|
|
170
186
|
export declare function countRedundantFragments(group: CountedOccurrence[]): number;
|
|
187
|
+
/** Adds the 1-based code lines the segment's matched tokens cover; shared with cross-file coverage. */
|
|
188
|
+
export declare function collectSegmentLines(segment: {
|
|
189
|
+
startTokenIndex: number;
|
|
190
|
+
endTokenIndex: number;
|
|
191
|
+
}, tokens: Token[], codeLineNumbers: Set<number> | undefined, duplicatedLines: Set<number>): void;
|
|
171
192
|
export {};
|
package/dist/duplication.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{dedupeByRegion as e,selectMaximalGroups as t}from"./duplicateSelection.js";const n=new Set(`statement_block.block.compound_statement.body_statement.constructor_body.do_block.if_statement.for_statement.for_in_statement.enhanced_for_statement.for_range_loop.while_statement.do_statement.try_statement.try_with_resources_statement.with_statement.switch_statement.switch_expression.switch_case.switch_block_statement_group.switch_rule.case_clause.case_statement.match_statement.match_arm.except_clause.catch_clause.finally_clause.elif_clause.ensure.expression_statement.return_statement.return_expression.if_expression.for_expression.while_expression.loop_expression.match_expression.jsx_element.jsx_self_closing_element.if.unless.case.case_match.while.until.for.begin.when`.split(`.`)),r=new Set([`program`,`source_file`,`translation_unit`,`module`,`statement_block`,`block`,`compound_statement`,`body_statement`,`constructor_body`,`class_body`,`block_body`,`do_block`,`do`,`ensure`,`then`,`else`,`case_statement`,`switch_block_statement_group`,`switch_rule`,`expression_case`,`type_case`,`communication_case`,`default_case`]),i=new Set([`identifier`,`constant`,`instance_variable`,`class_variable`,`global_variable`]),a=new Set([`shorthand_property_identifier`,`shorthand_property_identifier_pattern`]),o=new Map([[`number`,`#num`],[`number_literal`,`#num`],[`integer`,`#num`],[`float`,`#num`],[`integer_literal`,`#num`],[`float_literal`,`#num`],[`int_literal`,`#num`],[`rune_literal`,`#char`],[`imaginary_literal`,`#num`],[`decimal_integer_literal`,`#num`],[`hex_integer_literal`,`#num`],[`octal_integer_literal`,`#num`],[`binary_integer_literal`,`#num`],[`decimal_floating_point_literal`,`#num`],[`hex_floating_point_literal`,`#num`],[`string_fragment`,`#str`],[`multiline_string_fragment`,`#str`],[`string_content`,`#str`],[`raw_string_content`,`#str`],[`heredoc_content`,`#str`],[`heredoc_beginning`,`#heredoc`],[`heredoc_end`,`#heredoc`],[`string`,`#str`],[`template_string`,`#str`],[`string_literal`,`#str`],[`interpreted_string_literal`,`#str`],[`raw_string_literal`,`#str`],[`raw_string`,`#str`],[`escape_sequence`,`#str`],[`char_literal`,`#char`],[`character_literal`,`#char`],[`character`,`#char`],[`regex_pattern`,`#regex`]]),s=new Set([`#num`,`#str`,`#char`,`#regex`]),c=new Set([`comment`,`line_comment`,`block_comment`]),l=new Set([`string_fragment`,`multiline_string_fragment`,`string_content`,`raw_string_content`,`escape_sequence`,`heredoc_content`]),u=new Set([`string_fragment`,`multiline_string_fragment`,`string_content`,`raw_string_content`,`escape_sequence`,`heredoc_content`,`string_start`,`string_end`]),d=new Map([[`call_expression`,`function`],[`method_invocation`,`name`],[`call`,`method`],[`attribute`,`attribute`],[`macro_invocation`,`macro`],[`field_access`,`field`],[`new_expression`,`constructor`],[`keyword_argument`,`name`],[`element_value_pair`,`key`],[`generic_function`,`function`],[`template_function`,`name`]]),f={minTokens:40,maxGapTokens:30,minSimilarityPercent:70};function p(e,t){return e*5>=t}function m(e,n,r){let i=r?.minTokens??f.minTokens,a=r?.maxGapTokens??f.maxGapTokens,o=r?.minSimilarityPercent??f.minSimilarityPercent,s=[],c=[],l=[];g(e,s,c,l);let u=C(s),d=[...T(s,u,c,i),...ee(s,u,l,i)],p=X(Y(t(d,e=>e.length>=2)),a),m=k(s,u,c,i,o,p);return ie([...p.filter(e=>e.length>0),...m],n,s)}function h(t,n){let r=n?.minTokens??f.minTokens,i=[],a=[],o=[];g(t,i,a,o);let s=C(i),c=T(i,s,a,r);for(let e of o){let t=e[0],n=e.at(-1);!t||!n||n.endTokenIndex-t.startTokenIndex<r||c.push(R(`s:${U(i,s,t.startTokenIndex,n.endTokenIndex)}`,t.startTokenIndex,n.endTokenIndex,t,n))}return{candidates:e(c),tokens:i,containerStatements:o}}function g(e,t,i,a){function o(e){let s=t.length,l=e.childCount===0?void 0:_(e);if(e.childCount===0)v(e,t);else if(l!==void 0)t.push(y(l,b(e,l),e.startPosition.row,e.endPosition.row));else if(!c.has(e.type)){let t=[],n=e.isNamed&&r.has(e.type);for(let r of e.children){let e=o(r);n&&r.isNamed&&!c.has(r.type)&&t.push(e)}n&&t.length>0&&a.push(t)}let u={startTokenIndex:s,endTokenIndex:t.length,startIndex:e.startIndex,endIndex:e.endIndex,startLine:e.startPosition.row+1,endLine:e.endPosition.row+1};return e.isNamed&&n.has(e.type)&&i.push(u),u}o(e)}function _(e){let t=e.isNamed?o.get(e.type):void 0;if(t!==void 0)return e.namedChildren.every(e=>u.has(e.type))?t:void 0}function v(e,t){if(c.has(e.type))return;let n=e.startPosition.row,r=e.endPosition.row;if(e.isNamed&&a.has(e.type)){t.push(y(e.text,void 0,n,r,!0),y(`:`,void 0,n,r),{kind:`id`,text:e.text,textHash:0,textHash2:0,startRow:n,endRow:r});return}if(e.isNamed&&i.has(e.type)&&!w(e)){t.push({kind:`id`,text:e.text,textHash:0,textHash2:0,startRow:n,endRow:r});return}let s=e.isNamed?o.get(e.type):void 0;s===void 0?t.push(y(e.text,void 0,n,r,e.isNamed)):t.push(y(s,b(e,s),n,r))}function y(e,t,n,r,i=!1){let a={kind:`text`,text:e,textHash:K(e),textHash2:q(e),startRow:n,endRow:r};return t!==void 0&&s.has(e)&&(a.literalHash=K(t),a.literalHash2=q(t)),i&&(a.isName=!0),a}function b(e,t){if(t!==`#str`&&t!==`#char`||l.has(e.type))return e.text;let n=e.namedChildren.filter(e=>l.has(e.type));return n.length>0?n.map(e=>e.text).join(``):S(e.text)}const x=new Set([`"`,`'`,"`"]);function S(e){let t=e[0];return e.length>=2&&t!==void 0&&x.has(t)&&e.endsWith(t)?e.slice(1,-1):e}function C(e){let t=new Int32Array(e.length+1);for(let[n,r]of e.entries())t[n+1]=(t[n]??0)+(r.literalHash===void 0?0:1);return t}function w(e){let t=e.parent;if(!t)return!1;if(t.type===`method_reference`||t.type===`call`&&t.childForFieldName(`function`)?.id===e.id||e.type===`constant`&&t.type===`call`&&t.childForFieldName(`receiver`)?.id===e.id||t.type===`method_invocation`&&t.childForFieldName(`object`)?.id===e.id&&/^\p{Lu}/u.test(e.text))return!0;if((t.type===`scoped_identifier`||t.type===`qualified_identifier`)&&(t.childForFieldName(`name`)?.id===e.id||t.childForFieldName(`path`)?.id===e.id)){let e=t;for(;e.parent&&(e.parent.type===`scoped_identifier`||e.parent.type===`qualified_identifier`||e.parent.type===`generic_function`||e.parent.type===`template_function`);)e=e.parent;if(e.parent?.type===`call_expression`&&e.parent.childForFieldName(`function`)?.id===e.id)return!0}if(t.type===`literal_element`&&t.parent?.type===`keyed_element`&&t.parent.namedChild(0)?.id===t.id)return!0;let n=d.get(t.type);return n!==void 0&&t.childForFieldName(n)?.id===e.id}function T(e,t,n,r){let i=[];for(let a of n)a.endTokenIndex-a.startTokenIndex<r||i.push(R(`b:${U(e,t,a.startTokenIndex,a.endTokenIndex)}`,a.startTokenIndex,a.endTokenIndex,a,a));return i}function ee(e,t,n,r){return E([{tokens:e,literalCountPrefix:t,containers:n}],r,!1).map(({candidate:e})=>e)}function E(e,t,n){let r=[],i=[],a=[];for(let[t,n]of e.entries())for(let e of n.containers)i.push(t),a.push(e);let o=t=>e[i[t]??0],s=new Map,c=a.map((e,n)=>O(o(n)?.tokens??[],e,t));for(let[e,t]of c.entries()){let n=i[e]??0;for(let[r,i]of t.windowKeysByStart.entries())for(let t of i){if(t===void 0)continue;let i=s.get(t);i?(i.count+=1,i.containerIndex!==e&&(i.containerIndex=-1),i.contextIndex!==n&&(i.contextIndex=-1),i.minStart=Math.min(i.minStart,r),i.maxStart=Math.max(i.maxStart,r)):s.set(t,{count:1,containerIndex:e,contextIndex:n,minStart:r,maxStart:r})}}let l=(e,t)=>{if(e===void 0)return!1;let r=s.get(e);return r===void 0||r.count<2?!1:n?r.contextIndex===-1:r.containerIndex===-1||r.maxStart-r.minStart>=t},u=e=>{let t=c[e.containerIndex]?.statementHashes??[],n=t[e.start];for(let r=e.start+1;r<e.start+e.length;r+=1)if(t[r]!==n)return!0;return!1},d=[];for(let[e,t]of c.entries())for(let[n,r]of t.windowKeysByStart.entries())for(let[i,a]of r.entries()){if(!l(a,i)||!u({containerIndex:e,start:n,length:i}))continue;let r=t.windowKeysByStart[n]?.[i+1],o=t.windowKeysByStart[n-1]?.[i+1];l(r,i+1)||l(o,i+1)||d.push({containerIndex:e,start:n,length:i})}let f=new Set(d.map(D)),p=d;for(;p.length>0;){let e=[];for(let t of p){let n=a[t.containerIndex],s=n?.[t.start],c=n?.[t.start+t.length-1],l=o(t.containerIndex);if(!s||!c||!l)continue;let u=`s:${U(l.tokens,l.literalCountPrefix,s.startTokenIndex,c.endTokenIndex)}`;r.push({candidate:R(u,s.startTokenIndex,c.endTokenIndex,s,c),contextIndex:i[t.containerIndex]??0}),e.push(t)}p=[];for(let t of e)for(let e of[t.start,t.start+1]){let n={containerIndex:t.containerIndex,start:e,length:t.length-1},r=c[t.containerIndex]?.windowKeysByStart[e]?.[n.length];f.has(D(n))||!l(r,n.length)||!u(n)||(f.add(D(n)),p.push(n))}}return r}function D(e){return`${e.containerIndex}:${e.start}:${e.length}`}function O(e,t,n){let r=t.map(t=>W(e,t.startTokenIndex,t.endTokenIndex)),i=[];for(let e=0;e<t.length;e+=1){let a=[],o=5381,s=0,c=Math.min(t.length,e+100);for(let i=e;i<c;i+=1){let c=t[i],l=r[i];if(!c||l===void 0)break;o=J(o,l),s+=c.endTokenIndex-c.startTokenIndex;let u=i-e+1;a[u]=u>=2&&s>=n?J(o,u):void 0}i.push(a)}return{windowKeysByStart:i,statementHashes:r}}function k(e,t,n,r,i,a){if(i>=100)return[];let o=A(n.filter(e=>{let n=e.endTokenIndex-e.startTokenIndex,i=(t[e.endTokenIndex]??0)-(t[e.startTokenIndex]??0);return n>=r&&!p(i,n)}).toSorted((e,t)=>e.startTokenIndex-t.startTokenIndex||t.endTokenIndex-e.endTokenIndex));if(o.length<2)return[];let s=o.map(e=>{let t=[];for(let[n,r]of a.entries())r.some(t=>t.startTokenIndex<e.endTokenIndex&&e.startTokenIndex<t.endTokenIndex)&&t.push(n);return t}),c=new Map,l=o.map(t=>te(e,t,c)),u=l.map(({sequence:e})=>re(e)),d=F(u),f=o.map((e,t)=>t),m=e=>{let t=e;for(;f[t]!==t;)t=f[t]??t;for(;f[e]!==t;){let n=f[e]??t;f[e]=t,e=n}return t};for(let[e,t]of d){let n=Math.floor(e/u.length),r=e%u.length,a=l[n],o=l[r],c=u[n],d=u[r];if(!(!a||!o||!c||!d)&&!((s[n]?.length??0)>0&&(s[r]?.length??0)>0)&&!(t*100<10*Math.min(c.size,d.size))&&!(ne(a,o)*100<=50*Math.max(a.contentTotal,o.contentTotal))&&I(a.sequence,o.sequence)*100>=i*Math.max(a.sequence.length,o.sequence.length)){let e=m(n),t=m(r);f[Math.max(e,t)]=Math.min(e,t)}}let h=new Map;for(let e of o.keys()){let t=m(e),n=h.get(t)??[];n.push(e),h.set(t,n)}let g=[];for(let e of h.values()){if(e.length<2)continue;let t=e.filter(e=>(s[e]?.length??0)===0),n=e.filter(e=>(s[e]?.length??0)>0);if(n.length===0){g.push(e.flatMap(e=>o[e]?[P(o[e])]:[]));continue}if(t.length===0)continue;let r=t=>e.some(e=>{let n=o[e];return n!==void 0&&t.startTokenIndex<n.endTokenIndex&&n.startTokenIndex<t.endTokenIndex}),i=[...new Set(n.flatMap(e=>s[e]??[]))].filter(e=>{let t=a[e];return t!==void 0&&t.length>0&&t.every(r)}).toSorted((e,t)=>e-t),[c,...l]=i;if(c!==void 0){let t=new Set,n=[];for(let r of e){let e=o[r];if(!e)continue;let c=[];for(let n of i)for(let r of a[n]??[])!t.has(r)&&r.startTokenIndex<e.endTokenIndex&&e.startTokenIndex<r.endTokenIndex&&(t.add(r),c.push({occurrence:r,groupIndex:n}));c.sort((e,t)=>e.occurrence.startTokenIndex-t.occurrence.startTokenIndex||e.occurrence.endTokenIndex-t.occurrence.endTokenIndex);let l=[],u=new Set;for(let{occurrence:e,groupIndex:t}of c)u.has(t)&&(n.push(M(l)),l=[],u.clear()),l.push(e),u.add(t);l.length>0&&n.push(M(l)),c.length===0&&(s[r]?.length??0)===0&&n.push(P(e))}n.sort((e,t)=>e.startTokenIndex-t.startTokenIndex||e.endTokenIndex-t.endTokenIndex);for(let e of n)e.sharedWithMergedGroup=void 0;a[c]=n;for(let e of l)a[e]=[]}else t.length>=2&&g.push(t.flatMap(e=>o[e]?[P(o[e])]:[]))}return g.sort(Z),g}function A(e){let t=[],n=[];for(let r of e){for(;n.length>0&&n.at(-1).range.endTokenIndex<=r.startTokenIndex;)n.pop();let e=n.at(-1);if(e&&e.range.startTokenIndex===r.startTokenIndex&&e.range.endTokenIndex===r.endTokenIndex)continue;let i={range:r,children:[]};e?e.children.push(i):t.push(i),n.push(i)}let r=[],i=e=>{if(j(e))for(let t of e.children)i(t);else r.push(e.range)};for(let e of t)i(e);return r}function j(e){let[t]=e.children;return e.children.length>=2||t!==void 0&&j(t)}function M(e){let t=e[0];if(!t||e.length===1)return t??N();let n=[];for(let t of e.flatMap(e=>e.segments).toSorted((e,t)=>e.startTokenIndex-t.startTokenIndex||e.endTokenIndex-t.endTokenIndex)){let e=n.at(-1);e&&t.startTokenIndex<e.endTokenIndex?e.endTokenIndex=Math.max(e.endTokenIndex,t.endTokenIndex):n.push({...t})}return{segments:n,tokenCount:n.reduce((e,t)=>e+t.endTokenIndex-t.startTokenIndex,0),startTokenIndex:Math.min(...e.map(e=>e.startTokenIndex)),endTokenIndex:Math.max(...e.map(e=>e.endTokenIndex)),startIndex:Math.min(...e.map(e=>e.startIndex)),endIndex:Math.max(...e.map(e=>e.endIndex)),startLine:Math.min(...e.map(e=>e.startLine)),endLine:Math.max(...e.map(e=>e.endLine))}}function N(){return{segments:[],tokenCount:0,startTokenIndex:0,endTokenIndex:0,startIndex:0,endIndex:0,startLine:0,endLine:0}}function P(e){return{segments:[{startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex}],tokenCount:e.endTokenIndex-e.startTokenIndex,startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex,startIndex:e.startIndex,endIndex:e.endIndex,startLine:e.startLine,endLine:e.endLine}}function te(e,t,n){let r=new Int32Array(t.endTokenIndex-t.startTokenIndex),i=new Map,a=new Map,o=0;for(let s=t.startTokenIndex;s<t.endTokenIndex;s+=1){let c=e[s];if(!c)continue;let l;if(c.kind===`id`){let e=i.get(c.text);e===void 0&&(e=i.size,i.set(c.text,e)),l=-(e+1)}else{let e=`${c.textHash}:${c.textHash2}:${c.literalHash??0}:${c.literalHash2??0}`,t=n.get(e);t===void 0&&(t=n.size,n.set(e,t)),l=t,(c.isName===!0||c.literalHash!==void 0)&&(a.set(l,(a.get(l)??0)+1),o+=1)}r[s-t.startTokenIndex]=l}return{sequence:r,contentCountBySymbol:a,contentTotal:o}}function ne(e,t){let[n,r]=e.contentCountBySymbol.size<=t.contentCountBySymbol.size?[e,t]:[t,e],i=0;for(let[e,t]of n.contentCountBySymbol)i+=Math.min(t,r.contentCountBySymbol.get(e)??0);return i}function re(e){let t=new Set;for(let n=0;n+5<=e.length;n+=1){let r=5381;for(let t=0;t<5;t+=1)r=Math.imul(r,31)+(e[n+t]??0)|0;t.add(r)}return t}function F(e){let t=new Map;for(let[n,r]of e.entries())for(let e of r){let r=t.get(e);r||(r=[],t.set(e,r)),r.push(n)}let n=new Map;for(let r of t.values())for(let t=0;t<r.length;t+=1){let i=r[t]??0;for(let a=t+1;a<r.length;a+=1){let t=i*e.length+(r[a]??0);n.set(t,(n.get(t)??0)+1)}}return n}function I(e,t){let n=e.length+31>>>5,r=new Map;for(let[t,i]of e.entries()){let e=r.get(i);e||(e=new Uint32Array(n),r.set(i,e));let a=t>>>5;e[a]=(e[a]??0)|1<<(t&31)}let i=new Uint32Array(n);for(let e of t){let t=r.get(e),a=1,o=0;for(let e=0;e<n;e+=1){let n=i[e]??0,r=((t?.[e]??0)|n)>>>0,s=(n<<1|a)>>>0;a=n>>>31;let c=r-s-o;o=+(c<0),i[e]=r&~c}}let a=0;for(let e of i)a+=L(e);return a}function L(e){let t=e-(e>>>1&1431655765);return t=(t&858993459)+(t>>>2&858993459),Math.imul(t+(t>>>4)&252645135,16843009)>>>24&255}function R(e,t,n,r,i){return{fingerprint:e,tokenCount:n-t,startTokenIndex:t,endTokenIndex:n,startIndex:r.startIndex,endIndex:i.endIndex,startLine:r.startLine,endLine:i.endLine}}const z=[],B=[];function V(e){let t=z[e];return t===void 0&&(t=K(`$${e}`),z[e]=t),t}function H(e){let t=B[e];return t===void 0&&(t=q(`$${e}`),B[e]=t),t}function U(e,t,n,r){let[i,a]=G(e,n,r,p((t[r]??0)-(t[n]??0),r-n));return`${i}:${a}:${r-n}`}function W(e,t,n){let[r,i]=G(e,t,n,!1);return r^Math.imul(i,31)}function G(e,t,n,r){let i=new Map,a=5381,o=52711;for(let s=t;s<n;s+=1){let t=e[s];if(!t)continue;let n,c;if(t.kind===`id`){let e=i.get(t.text);e===void 0&&(e=i.size,i.set(t.text,e)),n=V(e),c=H(e)}else n=t.textHash,c=t.textHash2;a=Math.imul(a,31)+n|0,o=Math.imul(o,37)^c,r&&t.literalHash!==void 0&&t.literalHash2!==void 0&&(a=Math.imul(a,31)+t.literalHash|0,o=Math.imul(o,37)^t.literalHash2)}return[a,o]}function K(e){let t=5381;for(let n=0;n<e.length;n+=1)t=Math.imul(t,33)^e.charCodeAt(n);return t}function q(e){let t=-2128831035;for(let n=0;n<e.length;n+=1)t=Math.imul(t^e.charCodeAt(n),16777619);return t}function J(e,t){return Math.imul(e,31)+t}function Y(e){let t=[];for(let n of e.values()){let e=n.map(e=>({segments:[{startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex}],tokenCount:e.tokenCount,startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex,startIndex:e.startIndex,endIndex:e.endIndex,startLine:e.startLine,endLine:e.endLine}));e.sort((e,t)=>e.startTokenIndex-t.startTokenIndex||e.endTokenIndex-t.endTokenIndex),t.push(e)}return t}function X(e,t){if(t<=0||e.length<2)return e;e.sort(Z);for(let n=!0;n;){n=!1;for(let r=0;r<e.length&&!n;r+=1)for(let i=r+1;i<e.length;i+=1){let a=e[r],o=e[i];if(!a||!o)continue;let s=Q(a,o,t),c=s??Q(o,a,t);if(!c)continue;let l=s?c.firstConsumed:c.secondConsumed,u=s?c.secondConsumed:c.firstConsumed;l&&u?(e[r]=c.merged,e.splice(i,1)):u?e[i]=c.merged:e[r]=c.merged;for(let e of c.pairedRetained)e.sharedWithMergedGroup=!0;e.sort(Z),n=!0;break}}return e}function Z(e,t){let n=e[0],r=t[0];return(n?.startTokenIndex??0)-(r?.startTokenIndex??0)||(n?.endTokenIndex??0)-(r?.endTokenIndex??0)}function Q(e,t,n){let r=e.filter(e=>!e.sharedWithMergedGroup),i=t.filter(e=>!e.sharedWithMergedGroup),a=[],o=0,s=-1;for(let e of i){for(;o<r.length;){let t=r[o];if(t&&t.endTokenIndex+n<e.startTokenIndex)o+=1;else break}let t=r[o];t&&t.endTokenIndex<=e.startTokenIndex&&t.startTokenIndex>=s&&(a.push([t,e]),s=e.endTokenIndex,o+=1)}let c=a.length===e.length,l=a.length===t.length;if(!(a.length<2||!c&&!l))return{merged:a.map(([e,t])=>({...e,sharedWithMergedGroup:void 0,segments:[...e.segments,...t.segments],tokenCount:e.tokenCount+t.tokenCount,endTokenIndex:t.endTokenIndex,endIndex:t.endIndex,endLine:t.endLine})),firstConsumed:c,secondConsumed:l,pairedRetained:c===l?[]:a.map(([e,t])=>c?t:e)}}function $(e){let t=0,n=0,r=!1;for(let i of e){if(i.sharedWithMergedGroup){r=!0;continue}t+=i.segments.length,n=Math.max(n,i.segments.length)}return r?t:t-n}function ie(e,t,n){let r=0,i=0,a=[],o=new Set;for(let s of e){r+=$(s);for(let e of s){i=Math.max(i,e.tokenCount);for(let r of e.segments)for(let e=r.startTokenIndex;e<r.endTokenIndex;e+=1){let r=n[e];for(let e=r?.startRow??0;e<=(r?.endRow??-1);e+=1)t.has(e+1)&&o.add(e+1)}}a.push(s.map(({startLine:e,endLine:t})=>({startLine:e,endLine:t})).toSorted((e,t)=>e.startLine-t.startLine))}return a.sort((e,t)=>(e[0]?.startLine??0)-(t[0]?.startLine??0)),{duplicateBlockCount:r,duplicateBlockGroupCount:e.length,duplicateBlockGroups:a,duplicateLineCount:o.size,duplicationRatio:t.size===0?0:o.size/t.size,maxDuplicateBlockSize:i}}export{C as buildLiteralCountPrefix,h as collectCrossFileDuplicateCandidates,E as collectSequenceWindowCandidates,$ as countRedundantFragments,f as defaultDuplicationOptions,m as measureDuplication,X as mergeAdjacentGroups};
|
|
1
|
+
import{dedupeByRegion as e,selectMaximalGroups as t}from"./duplicateSelection.js";const n=new Set(`statement_block.block.compound_statement.body_statement.constructor_body.do_block.if_statement.for_statement.for_in_statement.enhanced_for_statement.for_range_loop.while_statement.do_statement.try_statement.try_with_resources_statement.with_statement.switch_statement.switch_expression.switch_case.switch_block_statement_group.switch_rule.case_clause.case_statement.match_statement.match_arm.except_clause.catch_clause.finally_clause.elif_clause.ensure.expression_statement.return_statement.return_expression.if_expression.for_expression.while_expression.loop_expression.match_expression.jsx_element.jsx_self_closing_element.if.unless.case.case_match.while.until.for.begin.when`.split(`.`)),r=new Set([`program`,`source_file`,`translation_unit`,`module`,`statement_block`,`block`,`compound_statement`,`body_statement`,`constructor_body`,`class_body`,`block_body`,`do_block`,`do`,`ensure`,`then`,`else`,`case_statement`,`switch_block_statement_group`,`switch_rule`,`expression_case`,`type_case`,`communication_case`,`default_case`]),i=new Set([`identifier`,`constant`,`instance_variable`,`class_variable`,`global_variable`]),a=new Set([`shorthand_property_identifier`,`shorthand_property_identifier_pattern`]),o=new Map([[`number`,`#num`],[`number_literal`,`#num`],[`integer`,`#num`],[`float`,`#num`],[`integer_literal`,`#num`],[`float_literal`,`#num`],[`int_literal`,`#num`],[`rune_literal`,`#char`],[`imaginary_literal`,`#num`],[`decimal_integer_literal`,`#num`],[`hex_integer_literal`,`#num`],[`octal_integer_literal`,`#num`],[`binary_integer_literal`,`#num`],[`decimal_floating_point_literal`,`#num`],[`hex_floating_point_literal`,`#num`],[`string_fragment`,`#str`],[`multiline_string_fragment`,`#str`],[`string_content`,`#str`],[`raw_string_content`,`#str`],[`heredoc_content`,`#str`],[`heredoc_beginning`,`#heredoc`],[`heredoc_end`,`#heredoc`],[`string`,`#str`],[`template_string`,`#str`],[`string_literal`,`#str`],[`interpreted_string_literal`,`#str`],[`raw_string_literal`,`#str`],[`raw_string`,`#str`],[`escape_sequence`,`#str`],[`char_literal`,`#char`],[`character_literal`,`#char`],[`character`,`#char`],[`regex_pattern`,`#regex`]]),s=new Set([`#num`,`#str`,`#char`,`#regex`]),c=new Set([`comment`,`line_comment`,`block_comment`]),l=new Set([`string_fragment`,`multiline_string_fragment`,`string_content`,`raw_string_content`,`escape_sequence`,`heredoc_content`]),u=new Set([`string_fragment`,`multiline_string_fragment`,`string_content`,`raw_string_content`,`escape_sequence`,`heredoc_content`,`string_start`,`string_end`]),d=new Map([[`call_expression`,`function`],[`method_invocation`,`name`],[`call`,`method`],[`attribute`,`attribute`],[`macro_invocation`,`macro`],[`field_access`,`field`],[`new_expression`,`constructor`],[`keyword_argument`,`name`],[`element_value_pair`,`key`],[`generic_function`,`function`],[`template_function`,`name`]]),f={minTokens:40,maxGapTokens:30,minSimilarityPercent:70};function p(e,t){return e*5>=t}function m(e,n,r){let i=r?.minTokens??f.minTokens,a=r?.maxGapTokens??f.maxGapTokens,o=r?.minSimilarityPercent??f.minSimilarityPercent,s=[],c=[],l=[];g(e,s,c,l);let u=C(s),d=[...T(s,u,c,i),...E(s,u,l,i)],p=Y(J(t(d,e=>e.length>=2)),a),m=A(s,u,c,i,o,p);return ae([...p.filter(e=>e.length>0),...m],n,s)}function h(t,n){let r=n?.minTokens??f.minTokens,i=[],a=[],o=[];g(t,i,a,o);let s=C(i),c=T(i,s,a,r);for(let e of o){let t=e[0],n=e.at(-1);!t||!n||n.endTokenIndex-t.startTokenIndex<r||c.push(L(`s:${H(i,s,t.startTokenIndex,n.endTokenIndex)}`,t.startTokenIndex,n.endTokenIndex,t,n))}return{candidates:e(c),tokens:i,containerStatements:o}}function g(e,t,i,a){function o(e){let s=t.length,l=e.childCount===0?void 0:_(e);if(e.childCount===0)v(e,t);else if(l!==void 0)t.push(y(l,b(e,l),e.startPosition.row,e.endPosition.row));else if(!c.has(e.type)){let t=[],n=e.isNamed&&r.has(e.type);for(let r of e.children){let e=o(r);n&&r.isNamed&&!c.has(r.type)&&t.push(e)}n&&t.length>0&&a.push(t)}let u={startTokenIndex:s,endTokenIndex:t.length,startIndex:e.startIndex,endIndex:e.endIndex,startLine:e.startPosition.row+1,endLine:e.endPosition.row+1};return e.isNamed&&n.has(e.type)&&i.push(u),u}o(e)}function _(e){let t=e.isNamed?o.get(e.type):void 0;if(t!==void 0)return e.namedChildren.every(e=>u.has(e.type))?t:void 0}function v(e,t){if(c.has(e.type))return;let n=e.startPosition.row,r=e.endPosition.row;if(e.isNamed&&a.has(e.type)){t.push(y(e.text,void 0,n,r,!0),y(`:`,void 0,n,r),{kind:`id`,text:e.text,textHash:0,textHash2:0,startRow:n,endRow:r});return}if(e.isNamed&&i.has(e.type)&&!w(e)){t.push({kind:`id`,text:e.text,textHash:0,textHash2:0,startRow:n,endRow:r});return}let s=e.isNamed?o.get(e.type):void 0;s===void 0?t.push(y(e.text,void 0,n,r,e.isNamed)):t.push(y(s,b(e,s),n,r))}function y(e,t,n,r,i=!1){let a={kind:`text`,text:e,textHash:G(e),textHash2:K(e),startRow:n,endRow:r};return t!==void 0&&s.has(e)&&(a.literalHash=G(t),a.literalHash2=K(t)),i&&(a.isName=!0),a}function b(e,t){if(t!==`#str`&&t!==`#char`||l.has(e.type))return e.text;let n=e.namedChildren.filter(e=>l.has(e.type));return n.length>0?n.map(e=>e.text).join(``):S(e.text)}const x=new Set([`"`,`'`,"`"]);function S(e){let t=e[0];return e.length>=2&&t!==void 0&&x.has(t)&&e.endsWith(t)?e.slice(1,-1):e}function C(e){let t=new Int32Array(e.length+1);for(let[n,r]of e.entries())t[n+1]=(t[n]??0)+(r.literalHash===void 0?0:1);return t}function w(e){let t=e.parent;if(!t)return!1;if(t.type===`method_reference`||t.type===`call`&&t.childForFieldName(`function`)?.id===e.id||e.type===`constant`&&t.type===`call`&&t.childForFieldName(`receiver`)?.id===e.id||t.type===`method_invocation`&&t.childForFieldName(`object`)?.id===e.id&&/^\p{Lu}/u.test(e.text))return!0;if((t.type===`scoped_identifier`||t.type===`qualified_identifier`)&&(t.childForFieldName(`name`)?.id===e.id||t.childForFieldName(`path`)?.id===e.id)){let e=t;for(;e.parent&&(e.parent.type===`scoped_identifier`||e.parent.type===`qualified_identifier`||e.parent.type===`generic_function`||e.parent.type===`template_function`);)e=e.parent;if(e.parent?.type===`call_expression`&&e.parent.childForFieldName(`function`)?.id===e.id)return!0}if(t.type===`literal_element`&&t.parent?.type===`keyed_element`&&t.parent.namedChild(0)?.id===t.id)return!0;let n=d.get(t.type);return n!==void 0&&t.childForFieldName(n)?.id===e.id}function T(e,t,n,r){let i=[];for(let a of n)a.endTokenIndex-a.startTokenIndex<r||i.push(L(`b:${H(e,t,a.startTokenIndex,a.endTokenIndex)}`,a.startTokenIndex,a.endTokenIndex,a,a));return i}function E(e,t,n,r){return D([{tokens:e,literalCountPrefix:t,containers:n}],r,!1).map(({candidate:e})=>e)}function D(e,t,n){let r=[],i=[],a=[];for(let[t,n]of e.entries())for(let e of n.containers)i.push(t),a.push(e);let o=t=>e[i[t]??0],s=new Map,c=a.map((e,n)=>k(o(n)?.tokens??[],e,t));for(let[e,t]of c.entries()){let n=i[e]??0;for(let[r,i]of t.windowKeysByStart.entries())for(let t of i){if(t===void 0)continue;let i=s.get(t);i?(i.count+=1,i.containerIndex!==e&&(i.containerIndex=-1),i.contextIndex!==n&&(i.contextIndex=-1),i.minStart=Math.min(i.minStart,r),i.maxStart=Math.max(i.maxStart,r)):s.set(t,{count:1,containerIndex:e,contextIndex:n,minStart:r,maxStart:r})}}let l=(e,t)=>{if(e===void 0)return!1;let r=s.get(e);return r===void 0||r.count<2?!1:n?r.contextIndex===-1:r.containerIndex===-1||r.maxStart-r.minStart>=t},u=e=>{let t=c[e.containerIndex]?.statementHashes??[],n=t[e.start];for(let r=e.start+1;r<e.start+e.length;r+=1)if(t[r]!==n)return!0;return!1},d=[];for(let[e,t]of c.entries())for(let[n,r]of t.windowKeysByStart.entries())for(let[i,a]of r.entries()){if(!l(a,i)||!u({containerIndex:e,start:n,length:i}))continue;let r=t.windowKeysByStart[n]?.[i+1],o=t.windowKeysByStart[n-1]?.[i+1];l(r,i+1)||l(o,i+1)||d.push({containerIndex:e,start:n,length:i})}let f=new Set(d.map(O)),p=d;for(;p.length>0;){let e=[];for(let t of p){let n=a[t.containerIndex],s=n?.[t.start],c=n?.[t.start+t.length-1],l=o(t.containerIndex);if(!s||!c||!l)continue;let u=`s:${H(l.tokens,l.literalCountPrefix,s.startTokenIndex,c.endTokenIndex)}`;r.push({candidate:L(u,s.startTokenIndex,c.endTokenIndex,s,c),contextIndex:i[t.containerIndex]??0}),e.push(t)}p=[];for(let t of e)for(let e of[t.start,t.start+1]){let n={containerIndex:t.containerIndex,start:e,length:t.length-1},r=c[t.containerIndex]?.windowKeysByStart[e]?.[n.length];f.has(O(n))||!l(r,n.length)||!u(n)||(f.add(O(n)),p.push(n))}}return r}function O(e){return`${e.containerIndex}:${e.start}:${e.length}`}function k(e,t,n){let r=t.map(t=>U(e,t.startTokenIndex,t.endTokenIndex)),i=[];for(let e=0;e<t.length;e+=1){let a=[],o=5381,s=0,c=Math.min(t.length,e+100);for(let i=e;i<c;i+=1){let c=t[i],l=r[i];if(!c||l===void 0)break;o=q(o,l),s+=c.endTokenIndex-c.startTokenIndex;let u=i-e+1;a[u]=u>=2&&s>=n?q(o,u):void 0}i.push(a)}return{windowKeysByStart:i,statementHashes:r}}function A(e,t,n,r,i,a){if(i>=100)return[];let o=ee(n.filter(e=>{let n=e.endTokenIndex-e.startTokenIndex,i=(t[e.endTokenIndex]??0)-(t[e.startTokenIndex]??0);return n>=r&&!p(i,n)}).toSorted((e,t)=>e.startTokenIndex-t.startTokenIndex||t.endTokenIndex-e.endTokenIndex));if(o.length<2)return[];let s=o.map(e=>{let t=[];for(let[n,r]of a.entries())r.some(t=>t.startTokenIndex<e.endTokenIndex&&e.startTokenIndex<t.endTokenIndex)&&t.push(n);return t}),c=new Map,l=o.map(t=>te(e,t,c)),u=l.map(({sequence:e})=>re(e)),d=ie(u),f=o.map((e,t)=>t),m=e=>{let t=e;for(;f[t]!==t;)t=f[t]??t;for(;f[e]!==t;){let n=f[e]??t;f[e]=t,e=n}return t};for(let[e,t]of d){let n=Math.floor(e/u.length),r=e%u.length,a=l[n],o=l[r],c=u[n],d=u[r];if(!(!a||!o||!c||!d)&&!((s[n]?.length??0)>0&&(s[r]?.length??0)>0)&&!(t*100<10*Math.min(c.size,d.size))&&!(ne(a,o)*100<=50*Math.max(a.contentTotal,o.contentTotal))&&F(a.sequence,o.sequence)*100>=i*Math.max(a.sequence.length,o.sequence.length)){let e=m(n),t=m(r);f[Math.max(e,t)]=Math.min(e,t)}}let h=new Map;for(let e of o.keys()){let t=m(e),n=h.get(t)??[];n.push(e),h.set(t,n)}let g=[];for(let e of h.values()){if(e.length<2)continue;let t=e.filter(e=>(s[e]?.length??0)===0),n=e.filter(e=>(s[e]?.length??0)>0);if(n.length===0){g.push(e.flatMap(e=>o[e]?[P(o[e])]:[]));continue}if(t.length===0)continue;let r=t=>e.some(e=>{let n=o[e];return n!==void 0&&t.startTokenIndex<n.endTokenIndex&&n.startTokenIndex<t.endTokenIndex}),i=[...new Set(n.flatMap(e=>s[e]??[]))].filter(e=>{let t=a[e];return t!==void 0&&t.length>0&&t.every(r)}).toSorted((e,t)=>e-t),[c,...l]=i;if(c!==void 0){let t=new Set,n=[];for(let r of e){let e=o[r];if(!e)continue;let c=[];for(let n of i)for(let r of a[n]??[])!t.has(r)&&r.startTokenIndex<e.endTokenIndex&&e.startTokenIndex<r.endTokenIndex&&(t.add(r),c.push({occurrence:r,groupIndex:n}));c.sort((e,t)=>e.occurrence.startTokenIndex-t.occurrence.startTokenIndex||e.occurrence.endTokenIndex-t.occurrence.endTokenIndex);let l=[],u=new Set;for(let{occurrence:e,groupIndex:t}of c)u.has(t)&&(n.push(M(l)),l=[],u.clear()),l.push(e),u.add(t);l.length>0&&n.push(M(l)),c.length===0&&(s[r]?.length??0)===0&&n.push(P(e))}n.sort((e,t)=>e.startTokenIndex-t.startTokenIndex||e.endTokenIndex-t.endTokenIndex);for(let e of n)e.sharedWithMergedGroup=void 0;a[c]=n;for(let e of l)a[e]=[]}else t.length>=2&&g.push(t.flatMap(e=>o[e]?[P(o[e])]:[]))}return g.sort(X),g}function ee(e){let t=[],n=[];for(let r of e){for(;n.length>0&&n.at(-1).range.endTokenIndex<=r.startTokenIndex;)n.pop();let e=n.at(-1);if(e&&e.range.startTokenIndex===r.startTokenIndex&&e.range.endTokenIndex===r.endTokenIndex)continue;let i={range:r,children:[]};e?e.children.push(i):t.push(i),n.push(i)}let r=[],i=e=>{if(j(e))for(let t of e.children)i(t);else r.push(e.range)};for(let e of t)i(e);return r}function j(e){let[t]=e.children;return e.children.length>=2||t!==void 0&&j(t)}function M(e){let t=e[0];if(!t||e.length===1)return t??N();let n=[];for(let t of e.flatMap(e=>e.segments).toSorted((e,t)=>e.startTokenIndex-t.startTokenIndex||e.endTokenIndex-t.endTokenIndex)){let e=n.at(-1);e&&t.startTokenIndex<e.endTokenIndex?e.endTokenIndex=Math.max(e.endTokenIndex,t.endTokenIndex):n.push({...t})}return{segments:n,tokenCount:n.reduce((e,t)=>e+t.endTokenIndex-t.startTokenIndex,0),startTokenIndex:Math.min(...e.map(e=>e.startTokenIndex)),endTokenIndex:Math.max(...e.map(e=>e.endTokenIndex)),startIndex:Math.min(...e.map(e=>e.startIndex)),endIndex:Math.max(...e.map(e=>e.endIndex)),startLine:Math.min(...e.map(e=>e.startLine)),endLine:Math.max(...e.map(e=>e.endLine))}}function N(){return{segments:[],tokenCount:0,startTokenIndex:0,endTokenIndex:0,startIndex:0,endIndex:0,startLine:0,endLine:0}}function P(e){return{segments:[{startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex}],tokenCount:e.endTokenIndex-e.startTokenIndex,startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex,startIndex:e.startIndex,endIndex:e.endIndex,startLine:e.startLine,endLine:e.endLine}}function te(e,t,n){let r=new Int32Array(t.endTokenIndex-t.startTokenIndex),i=new Map,a=new Map,o=0;for(let s=t.startTokenIndex;s<t.endTokenIndex;s+=1){let c=e[s];if(!c)continue;let l;if(c.kind===`id`){let e=i.get(c.text);e===void 0&&(e=i.size,i.set(c.text,e)),l=-(e+1)}else{let e=`${c.textHash}:${c.textHash2}:${c.literalHash??0}:${c.literalHash2??0}`,t=n.get(e);t===void 0&&(t=n.size,n.set(e,t)),l=t,(c.isName===!0||c.literalHash!==void 0)&&(a.set(l,(a.get(l)??0)+1),o+=1)}r[s-t.startTokenIndex]=l}return{sequence:r,contentCountBySymbol:a,contentTotal:o}}function ne(e,t){let[n,r]=e.contentCountBySymbol.size<=t.contentCountBySymbol.size?[e,t]:[t,e],i=0;for(let[e,t]of n.contentCountBySymbol)i+=Math.min(t,r.contentCountBySymbol.get(e)??0);return i}function re(e){let t=new Set;for(let n=0;n+5<=e.length;n+=1){let r=5381;for(let t=0;t<5;t+=1)r=Math.imul(r,31)+(e[n+t]??0)|0;t.add(r)}return t}function ie(e){let t=new Map;for(let[n,r]of e.entries())for(let e of r){let r=t.get(e);r||(r=[],t.set(e,r)),r.push(n)}let n=new Map;for(let r of t.values())for(let t=0;t<r.length;t+=1){let i=r[t]??0;for(let a=t+1;a<r.length;a+=1){let t=i*e.length+(r[a]??0);n.set(t,(n.get(t)??0)+1)}}return n}function F(e,t){let n=e.length+31>>>5,r=new Map;for(let[t,i]of e.entries()){let e=r.get(i);e||(e=new Uint32Array(n),r.set(i,e));let a=t>>>5;e[a]=(e[a]??0)|1<<(t&31)}let i=new Uint32Array(n);for(let e of t){let t=r.get(e),a=1,o=0;for(let e=0;e<n;e+=1){let n=i[e]??0,r=((t?.[e]??0)|n)>>>0,s=(n<<1|a)>>>0;a=n>>>31;let c=r-s-o;o=+(c<0),i[e]=r&~c}}let a=0;for(let e of i)a+=I(e);return a}function I(e){let t=e-(e>>>1&1431655765);return t=(t&858993459)+(t>>>2&858993459),Math.imul(t+(t>>>4)&252645135,16843009)>>>24&255}function L(e,t,n,r,i){return{fingerprint:e,tokenCount:n-t,startTokenIndex:t,endTokenIndex:n,startIndex:r.startIndex,endIndex:i.endIndex,startLine:r.startLine,endLine:i.endLine}}const R=[],z=[];function B(e){let t=R[e];return t===void 0&&(t=G(`$${e}`),R[e]=t),t}function V(e){let t=z[e];return t===void 0&&(t=K(`$${e}`),z[e]=t),t}function H(e,t,n,r){let[i,a]=W(e,n,r,p((t[r]??0)-(t[n]??0),r-n));return`${i}:${a}:${r-n}`}function U(e,t,n){let[r,i]=W(e,t,n,!1);return r^Math.imul(i,31)}function W(e,t,n,r){let i=new Map,a=5381,o=52711;for(let s=t;s<n;s+=1){let t=e[s];if(!t)continue;let n,c;if(t.kind===`id`){let e=i.get(t.text);e===void 0&&(e=i.size,i.set(t.text,e)),n=B(e),c=V(e)}else n=t.textHash,c=t.textHash2;a=Math.imul(a,31)+n|0,o=Math.imul(o,37)^c,r&&t.literalHash!==void 0&&t.literalHash2!==void 0&&(a=Math.imul(a,31)+t.literalHash|0,o=Math.imul(o,37)^t.literalHash2)}return[a,o]}function G(e){let t=5381;for(let n=0;n<e.length;n+=1)t=Math.imul(t,33)^e.charCodeAt(n);return t}function K(e){let t=-2128831035;for(let n=0;n<e.length;n+=1)t=Math.imul(t^e.charCodeAt(n),16777619);return t}function q(e,t){return Math.imul(e,31)+t}function J(e){let t=[];for(let n of e.values()){let e=n.map(e=>({segments:[{startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex}],tokenCount:e.tokenCount,startTokenIndex:e.startTokenIndex,endTokenIndex:e.endTokenIndex,startIndex:e.startIndex,endIndex:e.endIndex,startLine:e.startLine,endLine:e.endLine}));e.sort((e,t)=>e.startTokenIndex-t.startTokenIndex||e.endTokenIndex-t.endTokenIndex),t.push(e)}return t}function Y(e,t){if(t<=0||e.length<2)return e;e.sort(X);for(let n=!0;n;){n=!1;for(let r=0;r<e.length&&!n;r+=1)for(let i=r+1;i<e.length;i+=1){let a=e[r],o=e[i];if(!a||!o)continue;let s=Z(a,o,t),c=s??Z(o,a,t);if(!c)continue;let l=s?c.firstConsumed:c.secondConsumed,u=s?c.secondConsumed:c.firstConsumed;l&&u?(e[r]=c.merged,e.splice(i,1)):u?e[i]=c.merged:e[r]=c.merged;for(let e of c.pairedRetained)e.sharedWithMergedGroup=!0;e.sort(X),n=!0;break}}return e}function X(e,t){let n=e[0],r=t[0];return(n?.startTokenIndex??0)-(r?.startTokenIndex??0)||(n?.endTokenIndex??0)-(r?.endTokenIndex??0)}function Z(e,t,n){let r=e.filter(e=>!e.sharedWithMergedGroup),i=t.filter(e=>!e.sharedWithMergedGroup),a=[],o=0,s=-1;for(let e of i){for(;o<r.length;){let t=r[o];if(t&&t.endTokenIndex+n<e.startTokenIndex)o+=1;else break}let t=r[o];t&&t.endTokenIndex<=e.startTokenIndex&&t.startTokenIndex>=s&&(a.push([t,e]),s=e.endTokenIndex,o+=1)}let c=a.length===e.length,l=a.length===t.length;if(!(a.length<2||!c&&!l))return{merged:a.map(([e,t])=>({...e,sharedWithMergedGroup:void 0,segments:[...e.segments,...t.segments],tokenCount:e.tokenCount+t.tokenCount,endTokenIndex:t.endTokenIndex,endIndex:t.endIndex,endLine:t.endLine})),firstConsumed:c,secondConsumed:l,pairedRetained:c===l?[]:a.map(([e,t])=>c?t:e)}}function Q(e){let t=0,n=0,r=!1;for(let i of e){if(i.sharedWithMergedGroup){r=!0;continue}t+=i.segments.length,n=Math.max(n,i.segments.length)}return r?t:t-n}function ae(e,t,n){let r=0,i=0,a=[],o=new Set;for(let s of e){r+=Q(s);for(let e of s){i=Math.max(i,e.tokenCount);for(let r of e.segments)$(r,n,t,o)}a.push(s.map(({startLine:e,endLine:t})=>({startLine:e,endLine:t})).toSorted((e,t)=>e.startLine-t.startLine))}return a.sort((e,t)=>(e[0]?.startLine??0)-(t[0]?.startLine??0)),{duplicateBlockCount:r,duplicateBlockGroupCount:e.length,duplicateBlockGroups:a,duplicateLineCount:o.size,duplicateLineNumbers:[...o].toSorted((e,t)=>e-t),duplicationRatio:t.size===0?0:o.size/t.size,maxDuplicateBlockSize:i}}function $(e,t,n,r){for(let i=e.startTokenIndex;i<e.endTokenIndex;i+=1){let e=t[i];for(let t=e?.startRow??0;t<=(e?.endRow??-1);t+=1)(!n||n.has(t+1))&&r.add(t+1)}}export{C as buildLiteralCountPrefix,h as collectCrossFileDuplicateCandidates,$ as collectSegmentLines,D as collectSequenceWindowCandidates,Q as countRedundantFragments,f as defaultDuplicationOptions,G as hashText,F as lcsLength,m as measureDuplication,Y as mergeAdjacentGroups};
|
|
2
2
|
//# sourceMappingURL=duplication.js.map
|