Skip to content

Commit d2bba71

Browse files
authored
JS-728 Revert Write ast files to disk (#5432)
1 parent 2dbf69f commit d2bba71

26 files changed

Lines changed: 130 additions & 193 deletions

File tree

packages/bridge/src/delegate.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
* along with this program; if not, see https://sonarsource.com/license/ssal/
1616
*/
1717
import express from 'express';
18-
import { Worker } from 'node:worker_threads';
1918
import { handleRequest } from './handle-request.js';
20-
import { RequestResult, RequestType, WsIncrementalResult } from './request.js';
21-
import { WorkerData } from '../../shared/src/helpers/worker.js';
2219
import { info, debug, error } from '../../shared/src/helpers/logging.js';
20+
import type { Worker } from 'node:worker_threads';
21+
import type { RequestResult, RequestType, WsIncrementalResult } from './request.js';
22+
import type { WorkerData } from '../../shared/src/helpers/worker.js';
2323
import type { RawData, WebSocket } from 'ws';
24-
import { WorkerMessageListeners } from './router.js';
24+
import type { WorkerMessageListeners } from './router.js';
2525

2626
/**
2727
* Returns a delegate function to handle an HTTP request

packages/bridge/src/handle-request.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ import {
2828
} from '../../jsts/src/program/program.js';
2929
import { Linter } from '../../jsts/src/linter/linter.js';
3030
import { clearTypeScriptESLintParserCaches } from '../../jsts/src/parsers/eslint.js';
31-
import { BridgeRequest, RequestResult, serializeError, WsIncrementalResult } from './request.js';
32-
import { WorkerData } from '../../shared/src/helpers/worker.js';
31+
import {
32+
type BridgeRequest,
33+
type RequestResult,
34+
serializeError,
35+
type WsIncrementalResult,
36+
} from './request.js';
37+
import type { WorkerData } from '../../shared/src/helpers/worker.js';
3338

3439
export async function handleRequest(
3540
request: BridgeRequest,

packages/bridge/src/request.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@
1414
* You should have received a copy of the Sonar Source-Available License
1515
* along with this program; if not, see https://sonarsource.com/license/ssal/
1616
*/
17-
import { AnalysisOutput } from '../../shared/src/types/analysis.js';
18-
import {
19-
type FileResult,
17+
import type { AnalysisOutput } from '../../shared/src/types/analysis.js';
18+
import type {
19+
FileResult,
2020
ProjectAnalysisInput,
2121
ProjectAnalysisMeta,
2222
} from '../../jsts/src/analysis/projectAnalysis/projectAnalysis.js';
23-
import { TsConfigJson } from 'type-fest';
24-
import { RuleConfig } from '../../jsts/src/linter/config/rule-config.js';
23+
import type { TsConfigJson } from 'type-fest';
24+
import type { RuleConfig } from '../../jsts/src/linter/config/rule-config.js';
2525
import { APIError, ErrorCode } from '../../shared/src/errors/error.js';
26-
import { NamedDependency } from '../../jsts/src/rules/index.js';
27-
import { CssAnalysisInput } from '../../css/src/analysis/analysis.js';
28-
import { JsTsAnalysisInput } from '../../jsts/src/analysis/analysis.js';
29-
import { EmbeddedAnalysisInput } from '../../jsts/src/embedded/analysis/analysis.js';
26+
import type { NamedDependency } from '../../jsts/src/rules/index.js';
27+
import type { CssAnalysisInput } from '../../css/src/analysis/analysis.js';
28+
import type { JsTsAnalysisInput } from '../../jsts/src/analysis/analysis.js';
29+
import type { EmbeddedAnalysisInput } from '../../jsts/src/embedded/analysis/analysis.js';
3030

3131
export type RequestResult =
3232
| {

packages/bridge/tests/router.test.ts

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@ import { rule as S5362 } from '../../css/src/rules/S5362/index.js';
2626
import assert from 'node:assert';
2727
import { toUnixPath } from '../../shared/src/helpers/files.js';
2828
import { ProjectAnalysisInput } from '../../jsts/src/analysis/projectAnalysis/projectAnalysis.js';
29-
import { readProtobufFromFilePath } from '../../jsts/src/parsers/ast.js';
29+
import { deserializeProtobuf } from '../../jsts/src/parsers/ast.js';
3030
import { createAndSaveProgram } from '../../jsts/src/program/program.js';
3131
import { RuleConfig } from '../../jsts/src/linter/config/rule-config.js';
3232
import { createWorker } from '../../shared/src/helpers/worker.js';
33-
import { join } from 'node:path/posix';
3433

3534
describe('router', () => {
3635
const fixtures = path.join(import.meta.dirname, 'fixtures', 'router');
@@ -109,32 +108,28 @@ describe('router', () => {
109108
});
110109

111110
it('should route /analyze-jsts requests', async () => {
112-
await requestInitLinter(
113-
server,
114-
[
115-
{
116-
key: 'S6325',
117-
configurations: [],
118-
fileTypeTargets: ['MAIN'],
119-
language: 'js',
120-
analysisModes: ['DEFAULT'],
121-
},
122-
{
123-
key: 'S4621',
124-
configurations: [],
125-
fileTypeTargets: ['MAIN'],
126-
language: 'ts',
127-
analysisModes: ['DEFAULT'],
128-
},
129-
],
130-
join(fixtures, '.scannerwork'),
131-
);
111+
await requestInitLinter(server, [
112+
{
113+
key: 'S6325',
114+
configurations: [],
115+
fileTypeTargets: ['MAIN'],
116+
language: 'js',
117+
analysisModes: ['DEFAULT'],
118+
},
119+
{
120+
key: 'S4621',
121+
configurations: [],
122+
fileTypeTargets: ['MAIN'],
123+
language: 'ts',
124+
analysisModes: ['DEFAULT'],
125+
},
126+
]);
132127
let filePath = path.join(fixtures, 'file.js');
133128
let fileType = 'MAIN';
134129
let data: any = { filePath, fileType, tsConfigs: [] };
135130
let response = await request(server, '/analyze-jsts', 'POST', data);
136131
let {
137-
astFilePath,
132+
ast,
138133
issues: [issue],
139134
} = JSON.parse(response);
140135
expect(issue).toEqual(
@@ -147,7 +142,7 @@ describe('router', () => {
147142
message: `Use a regular expression literal instead of the 'RegExp' constructor.`,
148143
}),
149144
);
150-
const protoMessage = await readProtobufFromFilePath(astFilePath);
145+
const protoMessage = deserializeProtobuf(ast);
151146
expect(protoMessage.type).toEqual(0);
152147
expect(protoMessage.program.body).toHaveLength(1);
153148
expect(protoMessage.program.body[0].expressionStatement.expression.newExpression).toBeDefined();
@@ -362,7 +357,7 @@ describe('router', () => {
362357
});
363358
});
364359

365-
function requestInitLinter(server: http.Server, rules: RuleConfig[], rulesWorkdir?: string) {
366-
const config = { rules, rulesWorkdir };
360+
function requestInitLinter(server: http.Server, rules: RuleConfig[]) {
361+
const config = { rules };
367362
return request(server, '/init-linter', 'POST', config);
368363
}

packages/jsts/src/analysis/analysis.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export interface JsTsAnalysisOutput extends AnalysisOutput {
7575
}
7676

7777
export interface JsTsAnalysisOutputWithAst extends JsTsAnalysisOutput {
78-
astFilePath: string; // path to a binary encoded AST
78+
ast: string; // Base64 encoded Protobuf binary representation
7979
}
8080
/**
8181
* In SonarQube context, an analysis input includes both path and content of a file

packages/jsts/src/analysis/analyzer.ts

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ import { getCpdTokens } from '../linter/visitors/cpd.js';
3434
import { clearDependenciesCache, getAllDependencies } from '../rules/index.js';
3535
import { Telemetry } from '../../../bridge/src/request.js';
3636
import { fillFileContent } from '../../../shared/src/types/analysis.js';
37-
import { writeFile, mkdir } from 'node:fs/promises';
38-
import { join } from 'node:path/posix';
39-
import { randomBytes } from 'node:crypto';
4037

4138
/**
4239
* Analyzes a JavaScript / TypeScript analysis input
@@ -87,11 +84,11 @@ export async function analyzeJSTS(
8784
};
8885

8986
if (!input.skipAst) {
90-
const astFilePath = await serializeAst(parseResult.sourceCode, filePath, Linter.rulesWorkdir);
91-
if (astFilePath) {
87+
const ast = serializeAst(parseResult.sourceCode, filePath);
88+
if (ast) {
9289
return {
90+
ast,
9391
...result,
94-
astFilePath,
9592
};
9693
}
9794
}
@@ -107,27 +104,13 @@ export async function analyzeJSTS(
107104
}
108105
}
109106

110-
function generateRandomFilename(extension: string) {
111-
// 16 bytes = 32 hex characters
112-
const randomName = randomBytes(16).toString('hex');
113-
return randomName + extension;
114-
}
115-
116-
async function serializeAst(sourceCode: SourceCode, filePath: string, workdir: string | undefined) {
117-
if (!workdir) {
118-
return null;
119-
}
107+
function serializeAst(sourceCode: SourceCode, filePath: string) {
120108
try {
121-
const serializedAST = serializeInProtobuf(sourceCode.ast as TSESTree.Program, filePath);
122-
const astDir = join(workdir, 'asts');
123-
await mkdir(astDir, { recursive: true });
124-
const astFilePath = join(astDir, generateRandomFilename('.ast'));
125-
await writeFile(astFilePath, serializedAST);
126-
return astFilePath;
109+
return serializeInProtobuf(sourceCode.ast as TSESTree.Program, filePath);
127110
} catch (e) {
128111
info(`Failed to serialize AST for file "${filePath}"`);
112+
return null;
129113
}
130-
return null;
131114
}
132115

133116
/**

packages/jsts/src/analysis/projectAnalysis/analyzeWithProgram.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { tsConfigStore } from './file-stores/index.js';
2323
import ts from 'typescript';
2424
import { ProgressReport } from '../../../../shared/src/helpers/progress-report.js';
2525
import { handleFileResult } from './handleFileResult.js';
26-
import { WsIncrementalResult } from '../../../../bridge/src/request.js';
26+
import type { WsIncrementalResult } from '../../../../bridge/src/request.js';
2727

2828
/**
2929
* Analyzes JavaScript / TypeScript files using TypeScript programs. Files not

packages/jsts/src/analysis/projectAnalysis/handleFileResult.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* along with this program; if not, see https://sonarsource.com/license/ssal/
1616
*/
1717
import type { FileResult, ProjectAnalysisOutput } from './projectAnalysis.js';
18-
import { WsIncrementalResult } from '../../../../bridge/src/request.js';
18+
import type { WsIncrementalResult } from '../../../../bridge/src/request.js';
1919

2020
export function handleFileResult(
2121
result: FileResult,

packages/jsts/src/linter/linter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export class Linter {
9292
/** The global variables */
9393
public static readonly globals: Map<string, ESLintLinter.GlobalConf> = new Map();
9494
/** The rules working directory (used for ucfg, architecture, dbd...) */
95-
public static rulesWorkdir?: string;
95+
private static rulesWorkdir?: string;
9696
/** whether we are running in sonarlint context */
9797
private static sonarlint: boolean;
9898

packages/jsts/src/parsers/ast.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@
1515
* along with this program; if not, see https://sonarsource.com/license/ssal/
1616
*/
1717
import protobuf from 'protobufjs';
18+
import base64 from '@protobufjs/base64';
1819
import type { TSESTree } from '@typescript-eslint/utils';
1920

2021
import path from 'path';
2122
import { fileURLToPath } from 'node:url';
2223
import { debug } from '../../../shared/src/helpers/logging.js';
23-
import { readFile } from 'node:fs/promises';
2424

2525
const PATH_TO_PROTOFILE = path.join(path.dirname(fileURLToPath(import.meta.url)), 'estree.proto');
2626
const PROTO_ROOT = protobuf.loadSync(PATH_TO_PROTOFILE);
2727
const NODE_TYPE = PROTO_ROOT.lookupType('Node');
2828
export const NODE_TYPE_ENUM = PROTO_ROOT.lookupEnum('NodeType');
2929
const unsupportedNodeTypes = new Map<string, number>();
3030

31-
export function serializeInProtobuf(ast: TSESTree.Program, filePath: string) {
31+
export function serializeInProtobuf(ast: TSESTree.Program, filePath: string): string {
3232
unsupportedNodeTypes.clear();
3333
const protobufAST = parseInProtobuf(ast);
3434
if (unsupportedNodeTypes.size > 0) {
@@ -39,7 +39,8 @@ export function serializeInProtobuf(ast: TSESTree.Program, filePath: string) {
3939
.join(', '),
4040
);
4141
}
42-
return NODE_TYPE.encode(NODE_TYPE.create(protobufAST)).finish();
42+
const binaryArray = NODE_TYPE.encode(NODE_TYPE.create(protobufAST)).finish();
43+
return base64.encode(binaryArray, 0, binaryArray.length);
4344
}
4445

4546
/**
@@ -51,15 +52,14 @@ export function parseInProtobuf(ast: TSESTree.Program) {
5152
return protobufType.create(protobufShapedAST);
5253
}
5354

54-
export function deserializeProtobuf(buffer: Uint8Array) {
55-
return NODE_TYPE.decode(buffer);
56-
}
57-
5855
/**
5956
* Only used for tests
6057
*/
61-
export async function readProtobufFromFilePath(filePath: string): Promise<any> {
62-
return deserializeProtobuf(await readFile(filePath));
58+
export function deserializeProtobuf(serialized: string): any {
59+
const computedLength = base64.length(serialized);
60+
const buffer = new Uint8Array(computedLength);
61+
base64.decode(serialized, buffer, 0);
62+
return NODE_TYPE.decode(buffer);
6363
}
6464

6565
// Exported for testing purpose

0 commit comments

Comments
 (0)