Преглед изворни кода

SONAR-12334 Add primary location in snippets

tags/8.0
Jeremy пре 4 година
родитељ
комит
bf2da219c0

+ 6
- 1
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetViewer.tsx Прегледај датотеку

@@ -87,7 +87,12 @@ export default class ComponentSourceSnippetViewer extends React.PureComponent<Pr
}

createSnippetsFromProps() {
const snippets = createSnippets(this.props.snippetGroup.locations, this.props.last);
const snippets = createSnippets(
this.props.snippetGroup.locations,
this.props.last,
this.props.issue.secondaryLocations.length > 0 ? this.props.issue : undefined
);

this.setState({ snippets });
}


+ 24
- 1
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/ComponentSourceSnippetViewer-test.tsx Прегледај датотеку

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { mount, ReactWrapper, shallow } from 'enzyme';
import { times } from 'lodash';
import { range, times } from 'lodash';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { getSources } from '../../../../api/components';
@@ -45,6 +45,29 @@ it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should render correctly with secondary locations', () => {
// issue with secondary locations but no flows
const issue = mockIssue(true, {
flows: [],
textRange: { startLine: 5, endLine: 5, startOffset: 5, endOffset: 10 }
});

const snippetGroup: T.SnippetGroup = {
locations: [
mockFlowLocation({
component: 'a',
textRange: { startLine: 34, endLine: 34, startOffset: 0, endOffset: 0 }
}),
mockFlowLocation({
component: 'a',
textRange: { startLine: 54, endLine: 54, startOffset: 0, endOffset: 0 }
})
],
...mockSnippetsByComponent('a', [...range(3, 15), 32, 33, 34, 35, 36, 52, 53, 54, 55, 56])
};
expect(shallowRender({ issue, snippetGroup })).toMatchSnapshot();
});

it('should expand block', async () => {
(getSources as jest.Mock).mockResolvedValueOnce(
Object.values(mockSnippetsByComponent('a', [22, 23, 24, 25, 26, 27, 28, 29, 30, 31]).sources)

+ 607
- 0
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/ComponentSourceSnippetViewer-test.tsx.snap Прегледај датотеку

@@ -34,3 +34,610 @@ exports[`should render correctly 1`] = `
/>
</div>
`;

exports[`should render correctly with secondary locations 1`] = `
<div
className="component-source-container"
>
<SourceViewerHeaderSlim
branchLike={
Object {
"analysisDate": "2018-01-01",
"isMain": true,
"name": "master",
}
}
expandable={true}
loading={false}
onExpand={[Function]}
sourceViewerFile={
Object {
"key": "a",
"measures": Object {
"coverage": "85.2",
"duplicationDensity": "1.0",
"issues": "12",
"lines": "56",
},
"path": "a",
"project": "my-project",
"projectName": "MyProject",
"q": "FIL",
"uuid": "foo-bar",
}
}
/>
<div
id="snippet-wrapper-0"
key="0"
>
<SnippetViewer
branchLike={
Object {
"analysisDate": "2018-01-01",
"isMain": true,
"name": "master",
}
}
component={
Object {
"key": "a",
"measures": Object {
"coverage": "85.2",
"duplicationDensity": "1.0",
"issues": "12",
"lines": "56",
},
"path": "a",
"project": "my-project",
"projectName": "MyProject",
"q": "FIL",
"uuid": "foo-bar",
}
}
expandBlock={[Function]}
handleCloseIssues={[Function]}
handleLinePopupToggle={[Function]}
handleOpenIssues={[Function]}
handleSymbolClick={[Function]}
highlightedLocationMessage={
Object {
"index": 0,
"text": "",
}
}
highlightedSymbols={Array []}
index={0}
issue={
Object {
"actions": Array [],
"component": "main.js",
"componentLongName": "main.js",
"componentQualifier": "FIL",
"componentUuid": "foo1234",
"creationDate": "2017-03-01T09:36:01+0100",
"flows": Array [],
"fromHotspot": false,
"key": "AVsae-CQS-9G3txfbFN2",
"line": 25,
"message": "Reduce the number of conditional operators (4) used in the expression",
"organization": "myorg",
"project": "myproject",
"projectKey": "foo",
"projectName": "Foo",
"projectOrganization": "org",
"rule": "javascript:S1067",
"ruleName": "foo",
"secondaryLocations": Array [
Object {
"component": "main.js",
"textRange": Object {
"endLine": 2,
"endOffset": 2,
"startLine": 1,
"startOffset": 1,
},
},
Object {
"component": "main.js",
"textRange": Object {
"endLine": 2,
"endOffset": 2,
"startLine": 1,
"startOffset": 1,
},
},
],
"severity": "MAJOR",
"status": "OPEN",
"textRange": Object {
"endLine": 5,
"endOffset": 10,
"startLine": 5,
"startOffset": 5,
},
"transitions": Array [],
"type": "BUG",
}
}
issuesByLine={Object {}}
last={false}
loadDuplications={[Function]}
locations={Array []}
locationsByLine={Object {}}
onIssueChange={[MockFunction]}
onIssuePopupToggle={[MockFunction]}
onLocationSelect={[MockFunction]}
openIssuesByLine={Object {}}
renderDuplicationPopup={[Function]}
scroll={[MockFunction]}
snippet={
Array [
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 3,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 4,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 5,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 6,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 7,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 8,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 9,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 10,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 11,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 12,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 13,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 14,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
]
}
/>
</div>
<div
id="snippet-wrapper-1"
key="1"
>
<SnippetViewer
branchLike={
Object {
"analysisDate": "2018-01-01",
"isMain": true,
"name": "master",
}
}
component={
Object {
"key": "a",
"measures": Object {
"coverage": "85.2",
"duplicationDensity": "1.0",
"issues": "12",
"lines": "56",
},
"path": "a",
"project": "my-project",
"projectName": "MyProject",
"q": "FIL",
"uuid": "foo-bar",
}
}
expandBlock={[Function]}
handleCloseIssues={[Function]}
handleLinePopupToggle={[Function]}
handleOpenIssues={[Function]}
handleSymbolClick={[Function]}
highlightedLocationMessage={
Object {
"index": 0,
"text": "",
}
}
highlightedSymbols={Array []}
index={1}
issue={
Object {
"actions": Array [],
"component": "main.js",
"componentLongName": "main.js",
"componentQualifier": "FIL",
"componentUuid": "foo1234",
"creationDate": "2017-03-01T09:36:01+0100",
"flows": Array [],
"fromHotspot": false,
"key": "AVsae-CQS-9G3txfbFN2",
"line": 25,
"message": "Reduce the number of conditional operators (4) used in the expression",
"organization": "myorg",
"project": "myproject",
"projectKey": "foo",
"projectName": "Foo",
"projectOrganization": "org",
"rule": "javascript:S1067",
"ruleName": "foo",
"secondaryLocations": Array [
Object {
"component": "main.js",
"textRange": Object {
"endLine": 2,
"endOffset": 2,
"startLine": 1,
"startOffset": 1,
},
},
Object {
"component": "main.js",
"textRange": Object {
"endLine": 2,
"endOffset": 2,
"startLine": 1,
"startOffset": 1,
},
},
],
"severity": "MAJOR",
"status": "OPEN",
"textRange": Object {
"endLine": 5,
"endOffset": 10,
"startLine": 5,
"startOffset": 5,
},
"transitions": Array [],
"type": "BUG",
}
}
issuesByLine={Object {}}
last={false}
loadDuplications={[Function]}
locations={Array []}
locationsByLine={Object {}}
onIssueChange={[MockFunction]}
onIssuePopupToggle={[MockFunction]}
onLocationSelect={[MockFunction]}
openIssuesByLine={Object {}}
renderDuplicationPopup={[Function]}
scroll={[MockFunction]}
snippet={
Array [
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 32,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 33,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 34,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 35,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 36,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
]
}
/>
</div>
<div
id="snippet-wrapper-2"
key="2"
>
<SnippetViewer
branchLike={
Object {
"analysisDate": "2018-01-01",
"isMain": true,
"name": "master",
}
}
component={
Object {
"key": "a",
"measures": Object {
"coverage": "85.2",
"duplicationDensity": "1.0",
"issues": "12",
"lines": "56",
},
"path": "a",
"project": "my-project",
"projectName": "MyProject",
"q": "FIL",
"uuid": "foo-bar",
}
}
expandBlock={[Function]}
handleCloseIssues={[Function]}
handleLinePopupToggle={[Function]}
handleOpenIssues={[Function]}
handleSymbolClick={[Function]}
highlightedLocationMessage={
Object {
"index": 0,
"text": "",
}
}
highlightedSymbols={Array []}
index={2}
issue={
Object {
"actions": Array [],
"component": "main.js",
"componentLongName": "main.js",
"componentQualifier": "FIL",
"componentUuid": "foo1234",
"creationDate": "2017-03-01T09:36:01+0100",
"flows": Array [],
"fromHotspot": false,
"key": "AVsae-CQS-9G3txfbFN2",
"line": 25,
"message": "Reduce the number of conditional operators (4) used in the expression",
"organization": "myorg",
"project": "myproject",
"projectKey": "foo",
"projectName": "Foo",
"projectOrganization": "org",
"rule": "javascript:S1067",
"ruleName": "foo",
"secondaryLocations": Array [
Object {
"component": "main.js",
"textRange": Object {
"endLine": 2,
"endOffset": 2,
"startLine": 1,
"startOffset": 1,
},
},
Object {
"component": "main.js",
"textRange": Object {
"endLine": 2,
"endOffset": 2,
"startLine": 1,
"startOffset": 1,
},
},
],
"severity": "MAJOR",
"status": "OPEN",
"textRange": Object {
"endLine": 5,
"endOffset": 10,
"startLine": 5,
"startOffset": 5,
},
"transitions": Array [],
"type": "BUG",
}
}
issuesByLine={Object {}}
last={false}
loadDuplications={[Function]}
locations={Array []}
locationsByLine={Object {}}
onIssueChange={[MockFunction]}
onIssuePopupToggle={[MockFunction]}
onLocationSelect={[MockFunction]}
openIssuesByLine={Object {}}
renderDuplicationPopup={[Function]}
scroll={[MockFunction]}
snippet={
Array [
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 52,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 53,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 54,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 55,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
Object {
"code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;",
"coverageStatus": "covered",
"coveredConditions": 2,
"duplicated": false,
"isNew": true,
"line": 56,
"scmAuthor": "simon.brandhof@sonarsource.com",
"scmDate": "2018-12-11T10:48:39+0100",
"scmRevision": "80f564becc0c0a1c9abaa006eca83a4fd278c3f0",
},
]
}
/>
</div>
</div>
`;

+ 23
- 1
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/utils-test.ts Прегледај датотеку

@@ -17,7 +17,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { mockFlowLocation, mockSnippetsByComponent } from '../../../../helpers/testMocks';
import {
mockFlowLocation,
mockIssue,
mockSnippetsByComponent
} from '../../../../helpers/testMocks';
import { createSnippets, expandSnippet, groupLocationsByComponent } from '../utils';

describe('groupLocationsByComponent', () => {
@@ -138,6 +142,24 @@ describe('createSnippets', () => {
expect(results[0]).toEqual({ index: 0, start: 14, end: 24 });
expect(results[1]).toEqual({ index: 1, start: 45, end: 49 });
});

it("should prepend the issue's main location if necessary", () => {
const results = createSnippets(
[
mockFlowLocation({
textRange: { startLine: 47, startOffset: 2, endLine: 47, endOffset: 3 }
}),
mockFlowLocation({
textRange: { startLine: 22, startOffset: 2, endLine: 22, endOffset: 3 }
})
],
false,
mockIssue(false, { textRange: { startLine: 5, endLine: 5, startOffset: 0, endOffset: 0 } })
);

expect(results).toHaveLength(3);
expect(results[0]).toEqual({ index: 0, start: 3, end: 14 });
});
});

describe('expandSnippet', () => {

+ 53
- 34
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/utils.ts Прегледај датотеку

@@ -42,46 +42,65 @@ function collision([startA, endA]: number[], [startB, endB]: number[]) {
return !(startA > endB + MERGE_DISTANCE || endA < startB - MERGE_DISTANCE);
}

export function createSnippets(locations: T.FlowLocation[], last: boolean): T.Snippet[] {
function getPrimaryLocation(issue: T.Issue): T.FlowLocation {
return {
component: issue.component,
textRange: issue.textRange || {
endLine: 0,
endOffset: 0,
startLine: 0,
startOffset: 0
}
};
}

export function createSnippets(
locations: T.FlowLocation[],
last: boolean,
issue?: T.Issue
): T.Snippet[] {
// For each location's range (2 above and 2 below), and then compare with other ranges
// to merge snippets that collide.
return locations.reduce((snippets: T.Snippet[], loc, index) => {
const startIndex = Math.max(1, loc.textRange.startLine - LINES_ABOVE);
const endIndex =
loc.textRange.endLine +
(last && index === locations.length - 1 ? LINES_BELOW_LAST : LINES_BELOW);

let firstCollision: { start: number; end: number } | undefined;

// Remove ranges that collide into the first collision
snippets = snippets.filter(snippet => {
if (collision([snippet.start, snippet.end], [startIndex, endIndex])) {
let keep = false;
// Check if we've already collided
if (!firstCollision) {
firstCollision = snippet;
keep = true;
return (issue ? [getPrimaryLocation(issue), ...locations] : locations).reduce(
(snippets: T.Snippet[], loc, index) => {
const startIndex = Math.max(1, loc.textRange.startLine - LINES_ABOVE);
const endIndex =
loc.textRange.endLine +
(issue || (last && index === locations.length - 1) ? LINES_BELOW_LAST : LINES_BELOW);

let firstCollision: { start: number; end: number } | undefined;

// Remove ranges that collide into the first collision
snippets = snippets.filter(snippet => {
if (collision([snippet.start, snippet.end], [startIndex, endIndex])) {
let keep = false;
// Check if we've already collided
if (!firstCollision) {
firstCollision = snippet;
keep = true;
}
// Merge with first collision:
firstCollision.start = Math.min(startIndex, snippet.start, firstCollision.start);
firstCollision.end = Math.max(endIndex, snippet.end, firstCollision.end);

// remove the range if it was not the first collision
return keep;
}
// Merge with first collision:
firstCollision.start = Math.min(startIndex, snippet.start, firstCollision.start);
firstCollision.end = Math.max(endIndex, snippet.end, firstCollision.end);
return true;
});

// remove the range if it was not the first collision
return keep;
if (firstCollision === undefined) {
snippets.push({
start: startIndex,
end: endIndex,
index
});
}
return true;
});

if (firstCollision === undefined) {
snippets.push({
start: startIndex,
end: endIndex,
index
});
}

return snippets;
}, []);
return snippets;
},
[]
);
}

export function linesForSnippets(snippets: T.Snippet[], componentLines: T.LineMap) {

Loading…
Откажи
Сачувај