Add the assert-pure query

This query ensures that all of our files marked as "pure" remain that
way. In this case "pure" means that it does not depend on vscode and
can therefore be run in tests outside of a runtime environment.

This commit also explicitly moves all of our "pure" files to the
`src/pure` directory.
This commit is contained in:
Andrew Eisenberg
2020-10-31 11:44:05 -07:00
parent 2ac7881cf2
commit 5133ee713f
41 changed files with 104 additions and 49 deletions

12
.github/codeql/codeql-config.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
name: "CodeQL config"
queries:
- name: Run standard queries
uses: security-and-quality
- name: Run custom javascript queries
uses: ./.github/codeql/queries
paths:
- ./extensions/ql-vscode
paths-ignore:
- '**/node_modules'
- '**/build'
- '**/out'

21
.github/codeql/queries/assert-pure.ql vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* @name Unwanted dependency on vscode API
* @kind problem
* @problem.severity error
* @id vscode-codeql/assert-pure
* @description The modules stored under `pure` and tested in the `pure-tests`
* are intended to be "pure".
*/
import javascript
class VSCodeImport extends ASTNode {
VSCodeImport() {
this.(Import).getImportedPath().getValue() = "vscode"
}
}
from Module m, VSCodeImport v
where
m.getFile().getRelativePath().regexpMatch(".*src/pure/.*") and
m.getAnImportedModule*().getAnImport() = v
select m, "This module is not pure: it has a transitive dependency on the vscode API imported $@", v, "here"

3
.github/codeql/queries/qlpack.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
name: vscode-codeql-custom-queries-javascript
version: 0.0.0
libraryPathDependencies: codeql-javascript

View File

@@ -17,6 +17,9 @@ jobs:
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: javascript
config-file: ./.github/codeql/codeql-config.yml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -14,9 +14,9 @@ import {
import * as path from 'path';
import { DatabaseItem } from './databases';
import { UrlValue, BqrsId } from './bqrs-cli-types';
import { UrlValue, BqrsId } from './pure/bqrs-cli-types';
import { showLocation } from './interface-utils';
import { isStringLoc, isWholeFileLoc, isLineColumnLoc } from './bqrs-utils';
import { isStringLoc, isWholeFileLoc, isLineColumnLoc } from './pure/bqrs-utils';
import { commandRunner } from './helpers';
import { DisposableObject } from './vscode-utils/disposable-object';

View File

@@ -11,10 +11,10 @@ import * as tk from 'tree-kill';
import { promisify } from 'util';
import { CancellationToken, Disposable } from 'vscode';
import { BQRSInfo, DecodedBqrsChunk } from './bqrs-cli-types';
import { BQRSInfo, DecodedBqrsChunk } from './pure/bqrs-cli-types';
import { CliConfig } from './config';
import { DistributionProvider, FindDistributionResultKind } from './distribution';
import { assertNever } from './helpers-pure';
import { assertNever } from './pure/helpers-pure';
import { QueryMetadata, SortDirection } from './interface-types';
import { Logger, ProgressReporter } from './logging';

View File

@@ -19,7 +19,7 @@ import { Logger } from '../logging';
import { CodeQLCliServer } from '../cli';
import { DatabaseManager } from '../databases';
import { getHtmlForWebview, jumpToLocation } from '../interface-utils';
import { transformBqrsResultSet, RawResultSet, BQRSInfo } from '../bqrs-cli-types';
import { transformBqrsResultSet, RawResultSet, BQRSInfo } from '../pure/bqrs-cli-types';
import resultsDiff from './resultsDiff';
interface ComparePair {

View File

@@ -1,4 +1,4 @@
import { RawResultSet } from '../bqrs-cli-types';
import { RawResultSet } from '../pure/bqrs-cli-types';
import { QueryCompareResult } from '../interface-types';
/**

View File

@@ -3,7 +3,7 @@ import * as React from 'react';
import { SetComparisonsMessage } from '../../interface-types';
import RawTableHeader from '../../view/RawTableHeader';
import { className } from '../../view/result-table-utils';
import { ResultRow } from '../../bqrs-cli-types';
import { ResultRow } from '../../pure/bqrs-cli-types';
import RawTableRow from '../../view/RawTableRow';
import { vscode } from '../../view/vscode-api';

View File

@@ -1,6 +1,6 @@
import { QueryWithResults } from '../run-queries';
import { CodeQLCliServer } from '../cli';
import { DecodedBqrsChunk, BqrsId, EntityValue } from '../bqrs-cli-types';
import { DecodedBqrsChunk, BqrsId, EntityValue } from '../pure/bqrs-cli-types';
import { DatabaseItem } from '../databases';
import { ChildAstItem, AstItem } from '../astViewer';
import fileRangeFromURI from './fileRangeFromURI';

View File

@@ -1,7 +1,7 @@
import * as vscode from 'vscode';
import { UrlValue, LineColumnLocation } from '../bqrs-cli-types';
import { isEmptyPath } from '../bqrs-utils';
import { UrlValue, LineColumnLocation } from '../pure/bqrs-cli-types';
import { isEmptyPath } from '../pure/bqrs-utils';
import { DatabaseItem } from '../databases';

View File

@@ -1,11 +1,11 @@
import * as vscode from 'vscode';
import { decodeSourceArchiveUri, encodeArchiveBasePath } from '../archive-filesystem-provider';
import { ColumnKindCode, EntityValue, getResultSetSchema, ResultSetSchema } from '../bqrs-cli-types';
import { ColumnKindCode, EntityValue, getResultSetSchema, ResultSetSchema } from '../pure/bqrs-cli-types';
import { CodeQLCliServer } from '../cli';
import { DatabaseManager, DatabaseItem } from '../databases';
import fileRangeFromURI from './fileRangeFromURI';
import * as messages from '../messages';
import * as messages from '../pure/messages';
import { QueryServerClient } from '../queryserver-client';
import { QueryWithResults, compileAndRunQueryAgainstDatabase } from '../run-queries';
import { ProgressCallback } from '../helpers';

View File

@@ -4,7 +4,7 @@ import { decodeSourceArchiveUri, encodeArchiveBasePath, zipArchiveScheme } from
import { CodeQLCliServer } from '../cli';
import { DatabaseManager } from '../databases';
import { CachedOperation, ProgressCallback, withProgress } from '../helpers';
import * as messages from '../messages';
import * as messages from '../pure/messages';
import { QueryServerClient } from '../queryserver-client';
import { compileAndRunQueryAgainstDatabase, QueryWithResults } from '../run-queries';
import AstBuilder from './astBuilder';

View File

@@ -45,7 +45,7 @@ import {
GithubRateLimitedError
} from './distribution';
import * as helpers from './helpers';
import { assertNever } from './helpers-pure';
import { assertNever } from './pure/helpers-pure';
import { spawnIdeServer } from './ide-server';
import { InterfaceManager } from './interface';
import { WebviewReveal } from './interface-utils';
@@ -58,7 +58,7 @@ import { compileAndRunQueryAgainstDatabase, tmpDirDisposal } from './run-queries
import { QLTestAdapterFactory } from './test-adapter';
import { TestUIService } from './test-ui';
import { CompareInterfaceManager } from './compare/compare-interface';
import { gatherQlFiles } from './files';
import { gatherQlFiles } from './pure/files';
/**
* extension.ts

View File

@@ -1,5 +1,5 @@
import * as sarif from 'sarif';
import { RawResultSet, ResultRow, ResultSetSchema, Column, ResolvableLocationValue } from './bqrs-cli-types';
import { RawResultSet, ResultRow, ResultSetSchema, Column, ResolvableLocationValue } from './pure/bqrs-cli-types';
/**
* This module contains types and code that are shared between

View File

@@ -15,11 +15,16 @@ import {
import {
tryGetResolvableLocation,
isLineColumnLoc
} from './bqrs-utils';
} from './pure/bqrs-utils';
import { DatabaseItem, DatabaseManager } from './databases';
import { ViewSourceFileMsg } from './interface-types';
import { Logger } from './logging';
import { LineColumnLocation, WholeFileLocation, UrlValue, ResolvableLocationValue } from './bqrs-cli-types';
import {
LineColumnLocation,
WholeFileLocation,
UrlValue,
ResolvableLocationValue
} from './pure/bqrs-cli-types';
/**
* This module contains functions and types that are sharedd between

View File

@@ -15,7 +15,7 @@ import * as cli from './cli';
import { CodeQLCliServer } from './cli';
import { DatabaseEventKind, DatabaseItem, DatabaseManager } from './databases';
import { showAndLogErrorMessage } from './helpers';
import { assertNever } from './helpers-pure';
import { assertNever } from './pure/helpers-pure';
import {
FromResultsViewMsg,
Interpretation,
@@ -33,10 +33,10 @@ import {
} from './interface-types';
import { Logger } from './logging';
import { commandRunner } from './helpers';
import * as messages from './messages';
import * as messages from './pure/messages';
import { CompletedQuery, interpretResults } from './query-results';
import { QueryInfo, tmpDir } from './run-queries';
import { parseSarifLocation, parseSarifPlainTextMessage } from './sarif-utils';
import { parseSarifLocation, parseSarifPlainTextMessage } from './pure/sarif-utils';
import {
WebviewReveal,
fileUriToWebviewUri,
@@ -47,7 +47,7 @@ import {
jumpToLocation,
} from './interface-utils';
import { getDefaultResultSetName, ParsedResultSets } from './interface-types';
import { RawResultSet, transformBqrsResultSet, ResultSetSchema } from './bqrs-cli-types';
import { RawResultSet, transformBqrsResultSet, ResultSetSchema } from './pure/bqrs-cli-types';
/**
* interface.ts

View File

@@ -1,4 +1,9 @@
import { UrlValue, ResolvableLocationValue, LineColumnLocation, WholeFileLocation } from './bqrs-cli-types';
import {
UrlValue,
ResolvableLocationValue,
LineColumnLocation,
WholeFileLocation
} from './bqrs-cli-types';
/**
* The CodeQL filesystem libraries use this pattern in `getURL()` predicates

View File

@@ -1,7 +1,7 @@
import { env, TreeItem } from 'vscode';
import { QueryWithResults, tmpDir, QueryInfo } from './run-queries';
import * as messages from './messages';
import * as messages from './pure/messages';
import * as cli from './cli';
import * as sarif from 'sarif';
import * as fs from 'fs-extra';

View File

@@ -6,8 +6,8 @@ import { CancellationToken, createMessageConnection, MessageConnection, RequestT
import * as cli from './cli';
import { QueryServerConfig } from './config';
import { Logger, ProgressReporter } from './logging';
import { completeQuery, EvaluationResult, progress, ProgressMessage, WithProgressId } from './messages';
import * as messages from './messages';
import { completeQuery, EvaluationResult, progress, ProgressMessage, WithProgressId } from './pure/messages';
import * as messages from './pure/messages';
type ServerOpts = {
logger: Logger;

View File

@@ -18,7 +18,7 @@ import { DatabaseItem, getUpgradesDirectories } from './databases';
import * as helpers from './helpers';
import { DatabaseInfo, QueryMetadata, ResultsPaths } from './interface-types';
import { logger } from './logging';
import * as messages from './messages';
import * as messages from './pure/messages';
import { QueryHistoryItemOptions } from './query-history';
import * as qsClient from './queryserver-client';
import { isQuickQueryPath } from './quick-query';

View File

@@ -2,7 +2,7 @@ import * as vscode from 'vscode';
import { DatabaseItem } from './databases';
import * as helpers from './helpers';
import { logger } from './logging';
import * as messages from './messages';
import * as messages from './pure/messages';
import * as qsClient from './queryserver-client';
import { upgradesTmpDir } from './run-queries';

View File

@@ -3,7 +3,7 @@ import * as React from 'react';
import { vscode } from './vscode-api';
import { RawResultsSortState, SortDirection } from '../interface-types';
import { nextSortDirection } from './result-table-utils';
import { Column } from '../bqrs-cli-types';
import { Column } from '../pure/bqrs-cli-types';
interface Props {
readonly columns: readonly Column[];

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { ResultRow } from '../bqrs-cli-types';
import { ResultRow } from '../pure/bqrs-cli-types';
import { zebraStripe } from './result-table-utils';
import RawTableValue from './RawTableValue';

View File

@@ -1,7 +1,7 @@
import * as React from 'react';
import { renderLocation } from './result-table-utils';
import { ColumnValue } from '../bqrs-cli-types';
import { ColumnValue } from '../pure/bqrs-cli-types';
interface Props {
value: ColumnValue;

View File

@@ -6,10 +6,14 @@ import * as octicons from './octicons';
import { className, renderLocation, ResultTableProps, zebraStripe, selectableZebraStripe, jumpToLocation, nextSortDirection } from './result-table-utils';
import { onNavigation, NavigationEvent } from './results';
import { PathTableResultSet } from '../interface-types';
import { parseSarifPlainTextMessage, parseSarifLocation, isNoLocation } from '../sarif-utils';
import {
parseSarifPlainTextMessage,
parseSarifLocation,
isNoLocation
} from '../pure/sarif-utils';
import { InterpretedResultsSortColumn, SortDirection, InterpretedResultsSortState } from '../interface-types';
import { vscode } from './vscode-api';
import { isWholeFileLoc, isLineColumnLoc } from '../bqrs-utils';
import { isWholeFileLoc, isLineColumnLoc } from '../pure/bqrs-utils';
export type PathTableProps = ResultTableProps & { resultSet: PathTableResultSet };
export interface PathTableState {

View File

@@ -4,7 +4,7 @@ import { RAW_RESULTS_LIMIT, RawResultsSortState } from '../interface-types';
import { RawTableResultSet } from '../interface-types';
import RawTableHeader from './RawTableHeader';
import RawTableRow from './RawTableRow';
import { ResultRow } from '../bqrs-cli-types';
import { ResultRow } from '../pure/bqrs-cli-types';
export type RawTableProps = ResultTableProps & {
resultSet: RawTableResultSet;

View File

@@ -1,8 +1,8 @@
import * as React from 'react';
import { UrlValue, ResolvableLocationValue } from '../bqrs-cli-types';
import { isStringLoc, tryGetResolvableLocation } from '../bqrs-utils';
import { UrlValue, ResolvableLocationValue } from '../pure/bqrs-cli-types';
import { isStringLoc, tryGetResolvableLocation } from '../pure/bqrs-utils';
import { RawResultsSortState, QueryMetadata, SortDirection } from '../interface-types';
import { assertNever } from '../helpers-pure';
import { assertNever } from '../pure/helpers-pure';
import { ResultSet } from '../interface-types';
import { vscode } from './vscode-api';

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import * as Rdom from 'react-dom';
import { assertNever } from '../helpers-pure';
import { assertNever } from '../pure/helpers-pure';
import {
DatabaseInfo,
Interpretation,

View File

@@ -5,7 +5,7 @@ import { Uri, Range } from 'vscode';
import fileRangeFromURI from '../../../contextual/fileRangeFromURI';
import { DatabaseItem } from '../../../databases';
import { WholeFileLocation, LineColumnLocation } from '../../../bqrs-cli-types';
import { WholeFileLocation, LineColumnLocation } from '../../../pure/bqrs-cli-types';
describe('fileRangeFromURI', () => {
it('should return undefined when value is a string', () => {

View File

@@ -8,7 +8,7 @@ import * as chaiAsPromised from 'chai-as-promised';
import { CompletedQuery, interpretResults } from '../../query-results';
import { QueryInfo, QueryWithResults, tmpDir } from '../../run-queries';
import { QueryHistoryConfig } from '../../config';
import { EvaluationResult, QueryResultType } from '../../messages';
import { EvaluationResult, QueryResultType } from '../../pure/messages';
import { SortDirection, SortedResultSetInfo } from '../../interface-types';
import { CodeQLCliServer, SourceInfo } from '../../cli';

View File

@@ -5,11 +5,11 @@ import * as path from 'path';
import * as tmp from 'tmp';
import * as url from 'url';
import { CancellationTokenSource } from 'vscode-jsonrpc';
import * as messages from '../../messages';
import * as messages from '../../pure/messages';
import * as qsClient from '../../queryserver-client';
import * as cli from '../../cli';
import { ProgressReporter, Logger } from '../../logging';
import { ColumnValue } from '../../bqrs-cli-types';
import { ColumnValue } from '../../pure/bqrs-cli-types';
import { FindDistributionResultKind } from '../../distribution';

View File

@@ -6,7 +6,7 @@ import * as sinon from 'sinon';
import * as chaiAsPromised from 'chai-as-promised';
import { QueryInfo } from '../../run-queries';
import { QlProgram, Severity, compileQuery } from '../../messages';
import { QlProgram, Severity, compileQuery } from '../../pure/messages';
import { DatabaseItem } from '../../databases';
chai.use(chaiAsPromised);

View File

@@ -4,7 +4,7 @@ import * as sinonChai from 'sinon-chai';
import 'mocha';
import * as path from 'path';
import { gatherQlFiles } from '../../src/files';
import { gatherQlFiles } from '../../src/pure/files';
chai.use(sinonChai);
const expect = chai.expect;
@@ -13,9 +13,6 @@ describe('files', () => {
const dataDir = path.join(path.dirname(__dirname), 'data');
const data2Dir = path.join(path.dirname(__dirname), 'data2');
it('should pass', () => {
expect(true).to.be.eq(true);
});
it('should find one file', async () => {
const singleFile = path.join(dataDir, 'query.ql');
const result = await gatherQlFiles([singleFile]);

View File

@@ -1,6 +1,6 @@
import { expect } from 'chai';
import 'mocha';
import { tryGetResolvableLocation } from '../../src/bqrs-utils';
import { tryGetResolvableLocation } from '../../src/pure/bqrs-utils';
describe('processing string locations', function() {
it('should detect Windows whole-file locations', function() {

View File

@@ -2,7 +2,12 @@ import 'mocha';
import { expect } from 'chai';
import * as Sarif from 'sarif';
import { getPathRelativeToSourceLocationPrefix, parseSarifLocation, parseSarifPlainTextMessage, unescapeSarifText } from '../../src/sarif-utils';
import {
getPathRelativeToSourceLocationPrefix,
parseSarifLocation,
parseSarifPlainTextMessage,
unescapeSarifText
} from '../../src/pure/sarif-utils';
describe('parsing sarif', () => {