Skip to content

Commit ff2d67d

Browse files
author
Dave Bartolomeo
committed
Merge remote-tracking branch 'origin/main' into dbartol/save-before-start
2 parents ec71f53 + fa23441 commit ff2d67d

83 files changed

Lines changed: 1114 additions & 184 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/codeql/queries/assert-pure.ql renamed to .github/codeql/queries/assert-no-vscode-dependency.ql

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
* @name Unwanted dependency on vscode API
33
* @kind path-problem
44
* @problem.severity error
5-
* @id vscode-codeql/assert-pure
6-
* @description The modules stored under `pure` and tested in the `pure-tests`
7-
* are intended to be "pure".
5+
* @id vscode-codeql/assert-no-vscode-dependency
6+
* @description The modules stored under `common` should not have dependencies on the VS Code API
87
*/
98

109
import javascript
@@ -13,12 +12,9 @@ class VSCodeImport extends ImportDeclaration {
1312
VSCodeImport() { this.getImportedPath().getValue() = "vscode" }
1413
}
1514

16-
class PureFile extends File {
17-
PureFile() {
18-
(
19-
this.getRelativePath().regexpMatch(".*/src/pure/.*") or
20-
this.getRelativePath().regexpMatch(".*/src/common/.*")
21-
) and
15+
class CommonFile extends File {
16+
CommonFile() {
17+
this.getRelativePath().regexpMatch(".*/src/common/.*") and
2218
not this.getRelativePath().regexpMatch(".*/vscode/.*")
2319
}
2420
}
@@ -34,7 +30,8 @@ query predicate edges(AstNode a, AstNode b) {
3430

3531
from Module m, VSCodeImport v
3632
where
37-
m.getFile() instanceof PureFile and
33+
m.getFile() instanceof CommonFile and
3834
edges+(m, v)
3935
select m, m, v,
40-
"This module is not pure: it has a transitive dependency on the vscode API imported $@", v, "here"
36+
"This module is in the 'common' directory but has a transitive dependency on the vscode API imported $@",
37+
v, "here"

extensions/ql-vscode/src/codeql-cli/cli.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { walkDirectory } from "../common/files";
2626
import { QueryMetadata, SortDirection } from "../common/interface-types";
2727
import { BaseLogger, Logger } from "../common/logging";
2828
import { ProgressReporter } from "../common/logging/vscode";
29-
import { CompilationMessage } from "../pure/legacy-messages";
29+
import { CompilationMessage } from "../query-server/legacy-messages";
3030
import { sarifParser } from "../common/sarif-parser";
3131
import { App } from "../common/app";
3232
import { QueryLanguage } from "../common/query-language";

extensions/ql-vscode/src/common/commands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { AstItem } from "../language-support";
44
import type { DbTreeViewItem } from "../databases/ui/db-tree-view-item";
55
import type { DatabaseItem } from "../databases/local-databases";
66
import type { QueryHistoryInfo } from "../query-history/query-history-info";
7-
import type { RepositoriesFilterSortStateWithIds } from "../pure/variant-analysis-filter-sort";
7+
import type { RepositoriesFilterSortStateWithIds } from "../variant-analysis/shared/variant-analysis-filter-sort";
88
import type { TestTreeNode } from "../query-testing/test-tree-node";
99
import type {
1010
VariantAnalysis,

extensions/ql-vscode/src/common/files.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { pathExists, stat, readdir, opendir } from "fs-extra";
22
import { isAbsolute, join, relative, resolve } from "path";
3+
import { tmpdir as osTmpdir } from "os";
34

45
/**
56
* Recursively finds all .ql files in this set of Uris.
@@ -121,3 +122,8 @@ export interface IOError {
121122
export function isIOError(e: any): e is IOError {
122123
return e.code !== undefined && typeof e.code === "string";
123124
}
125+
126+
// This function is a wrapper around `os.tmpdir()` to make it easier to mock in tests.
127+
export function tmpdir(): string {
128+
return osTmpdir();
129+
}

extensions/ql-vscode/src/common/interface-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
import {
1515
RepositoriesFilterSortState,
1616
RepositoriesFilterSortStateWithIds,
17-
} from "../pure/variant-analysis-filter-sort";
17+
} from "../variant-analysis/shared/variant-analysis-filter-sort";
1818
import { ErrorLike } from "../common/errors";
1919
import { DataFlowPaths } from "../variant-analysis/shared/data-flow-paths";
2020
import { ExternalApiUsage } from "../data-extensions-editor/external-api-usage";

extensions/ql-vscode/src/config.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
FilterKey,
1515
SortKey,
1616
defaultFilterSortState,
17-
} from "./pure/variant-analysis-filter-sort";
17+
} from "./variant-analysis/shared/variant-analysis-filter-sort";
1818

1919
export const ALL_SETTINGS: Setting[] = [];
2020

@@ -731,7 +731,15 @@ export function showQueriesPanel(): boolean {
731731

732732
const DATA_EXTENSIONS = new Setting("dataExtensions", ROOT_SETTING);
733733
const LLM_GENERATION = new Setting("llmGeneration", DATA_EXTENSIONS);
734+
const DISABLE_AUTO_NAME_EXTENSION_PACK = new Setting(
735+
"disableAutoNameExtensionPack",
736+
DATA_EXTENSIONS,
737+
);
734738

735739
export function showLlmGeneration(): boolean {
736740
return !!LLM_GENERATION.getValue<boolean>();
737741
}
742+
743+
export function disableAutoNameExtensionPack(): boolean {
744+
return !!DISABLE_AUTO_NAME_EXTENSION_PACK.getValue<boolean>();
745+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
const packNamePartRegex = /[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
2+
const packNameRegex = new RegExp(
3+
`^(?<scope>${packNamePartRegex.source})/(?<name>${packNamePartRegex.source})$`,
4+
);
5+
const packNameLength = 128;
6+
7+
export interface ExtensionPackName {
8+
scope: string;
9+
name: string;
10+
}
11+
12+
export function formatPackName(packName: ExtensionPackName): string {
13+
return `${packName.scope}/${packName.name}`;
14+
}
15+
16+
export function autoNameExtensionPack(
17+
name: string,
18+
language: string,
19+
): ExtensionPackName | undefined {
20+
let packName = `${name}-${language}`;
21+
if (!packName.includes("/")) {
22+
packName = `pack/${packName}`;
23+
}
24+
25+
const parts = packName.split("/");
26+
const sanitizedParts = parts.map((part) => sanitizeExtensionPackName(part));
27+
28+
// If the scope is empty (e.g. if the given name is "-/b"), then we need to still set a scope
29+
if (sanitizedParts[0].length === 0) {
30+
sanitizedParts[0] = "pack";
31+
}
32+
33+
return {
34+
scope: sanitizedParts[0],
35+
// This will ensure there's only 1 slash
36+
name: sanitizedParts.slice(1).join("-"),
37+
};
38+
}
39+
40+
function sanitizeExtensionPackName(name: string) {
41+
// Lowercase everything
42+
name = name.toLowerCase();
43+
44+
// Replace all spaces, dots, and underscores with hyphens
45+
name = name.replaceAll(/[\s._]+/g, "-");
46+
47+
// Replace all characters which are not allowed by empty strings
48+
name = name.replaceAll(/[^a-z0-9-]/g, "");
49+
50+
// Remove any leading or trailing hyphens
51+
name = name.replaceAll(/^-|-$/g, "");
52+
53+
// Remove any duplicate hyphens
54+
name = name.replaceAll(/-{2,}/g, "-");
55+
56+
return name;
57+
}
58+
59+
export function parsePackName(packName: string): ExtensionPackName | undefined {
60+
const matches = packNameRegex.exec(packName);
61+
if (!matches?.groups) {
62+
return;
63+
}
64+
65+
const scope = matches.groups.scope;
66+
const name = matches.groups.name;
67+
68+
return {
69+
scope,
70+
name,
71+
};
72+
}
73+
74+
export function validatePackName(name: string): string | undefined {
75+
if (!name) {
76+
return "Pack name must not be empty";
77+
}
78+
79+
if (name.length > packNameLength) {
80+
return `Pack name must be no longer than ${packNameLength} characters`;
81+
}
82+
83+
const matches = packNameRegex.exec(name);
84+
if (!matches?.groups) {
85+
if (!name.includes("/")) {
86+
return "Invalid package name: a pack name must contain a slash to separate the scope from the pack name";
87+
}
88+
89+
return "Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens";
90+
}
91+
92+
return undefined;
93+
}

0 commit comments

Comments
 (0)