Extract tryGetResolvableLocation from semmle-bqrs
This commit is contained in:
64
extensions/ql-vscode/src/bqrs-utils.ts
Normal file
64
extensions/ql-vscode/src/bqrs-utils.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { StringLocation, LocationValue, LocationStyle, ResolvableLocationValue } from './bqrs-types';
|
||||
|
||||
/**
|
||||
* The CodeQL filesystem libraries use this pattern in `getURL()` predicates
|
||||
* to describe the location of an entire filesystem resource.
|
||||
* Such locations appear as `StringLocation`s instead of `FivePartLocation`s.
|
||||
*
|
||||
* Folder resources also get similar URLs, but with the `folder` scheme.
|
||||
* They are deliberately ignored here, since there is no suitable location to show the user.
|
||||
*/
|
||||
const FILE_LOCATION_REGEX = /file:\/\/(.+):([0-9]+):([0-9]+):([0-9]+):([0-9]+)/;
|
||||
/**
|
||||
* Gets a resolvable source file location for the specified `LocationValue`, if possible.
|
||||
* @param loc The location to test.
|
||||
*/
|
||||
export function tryGetResolvableLocation(
|
||||
loc: LocationValue | undefined
|
||||
): ResolvableLocationValue | undefined {
|
||||
if (loc === undefined) {
|
||||
return undefined;
|
||||
} else if (loc.t === LocationStyle.FivePart && loc.file) {
|
||||
return loc;
|
||||
} else if (loc.t === LocationStyle.WholeFile && loc.file) {
|
||||
return loc;
|
||||
} else if (loc.t === LocationStyle.String && loc.loc) {
|
||||
return tryGetLocationFromString(loc);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function tryGetLocationFromString(
|
||||
loc: StringLocation
|
||||
): ResolvableLocationValue | undefined {
|
||||
const matches = FILE_LOCATION_REGEX.exec(loc.loc);
|
||||
if (matches && matches.length > 1 && matches[1]) {
|
||||
if (isWholeFileMatch(matches)) {
|
||||
return {
|
||||
t: LocationStyle.WholeFile,
|
||||
file: matches[1],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
t: LocationStyle.FivePart,
|
||||
file: matches[1],
|
||||
lineStart: Number(matches[2]),
|
||||
colStart: Number(matches[3]),
|
||||
lineEnd: Number(matches[4]),
|
||||
colEnd: Number(matches[5]),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function isWholeFileMatch(matches: RegExpExecArray): boolean {
|
||||
return (
|
||||
matches[2] === "0" &&
|
||||
matches[3] === "0" &&
|
||||
matches[4] === "0" &&
|
||||
matches[5] === "0"
|
||||
);
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from './bqrs-types';
|
||||
import {
|
||||
tryGetResolvableLocation,
|
||||
} from 'semmle-bqrs';
|
||||
} from './bqrs-utils';
|
||||
import { DatabaseItem, DatabaseManager } from './databases';
|
||||
import { ViewSourceFileMsg } from './interface-types';
|
||||
import { Logger } from './logging';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { LocationValue, ResolvableLocationValue } from '../bqrs-types';
|
||||
import { tryGetResolvableLocation } from 'semmle-bqrs';
|
||||
import { tryGetResolvableLocation } from '../bqrs-utils';
|
||||
import { RawResultsSortState, QueryMetadata, SortDirection } from '../interface-types';
|
||||
import { assertNever } from '../helpers-pure';
|
||||
import { ResultSet } from '../interface-types';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import { LocationStyle, StringLocation } from '../../src/bqrs-types';
|
||||
import { tryGetResolvableLocation } from 'semmle-bqrs';
|
||||
import { tryGetResolvableLocation } from '../../src/bqrs-utils';
|
||||
|
||||
describe('processing string locations', function () {
|
||||
it('should detect Windows whole-file locations', function () {
|
||||
|
||||
Reference in New Issue
Block a user