Skip to content

Commit a0ba188

Browse files
authored
Merge pull request #96 from digma-ai/feature/detect_span_debug
Feature/detect span debug
2 parents 01167d5 + e4a03f1 commit a0ba188

20 files changed

+554
-229
lines changed

src/extension.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import { CodeAnalyticsView } from './views/codeAnalytics/codeAnalyticsView';
1313
import { ErrorsLineDecorator } from './decorators/errorsLineDecorator';
1414
import { HotspotMarkerDecorator } from './decorators/hotspotMarkerDecorator';
1515
import { EditorHelper } from './services/EditorHelper';
16-
import { CodeInvestigator } from './services/codeInvestigator';
16+
import { CodeInspector } from './services/codeInspector';
17+
import { VsCodeDebugInstrumentation } from './instrumentation/vscodeInstrumentation';
1718

1819
export async function activate(context: vscode.ExtensionContext)
1920
{
@@ -25,8 +26,8 @@ export async function activate(context: vscode.ExtensionContext)
2526
new Git()
2627
];
2728
const sourceControl = new SourceControl(supportedSourceControls);
28-
const codeInvestigator = new CodeInvestigator();
29-
const symbolProvider = new SymbolProvider(supportedLanguages, codeInvestigator);
29+
const codeInspector = new CodeInspector();
30+
const symbolProvider = new SymbolProvider(supportedLanguages, codeInspector);
3031
const analyticsProvider = new AnalyticsProvider();
3132
const documentInfoProvider = new DocumentInfoProvider(analyticsProvider, symbolProvider);
3233
const editorHelper = new EditorHelper(sourceControl, documentInfoProvider);
@@ -39,13 +40,14 @@ export async function activate(context: vscode.ExtensionContext)
3940
}
4041
context.subscriptions.push(new AnaliticsCodeLens(documentInfoProvider));
4142
context.subscriptions.push(new ContextView(analyticsProvider, context.extensionUri));
42-
context.subscriptions.push(new MethodCallErrorTooltip(documentInfoProvider, codeInvestigator));
43+
context.subscriptions.push(new MethodCallErrorTooltip(documentInfoProvider, codeInspector));
4344
context.subscriptions.push(sourceControl);
4445
context.subscriptions.push(documentInfoProvider);
4546
context.subscriptions.push(new CodeAnalyticsView(analyticsProvider, documentInfoProvider,
4647
context.extensionUri, editorHelper));
4748
context.subscriptions.push(new ErrorsLineDecorator(documentInfoProvider));
4849
context.subscriptions.push(new HotspotMarkerDecorator(documentInfoProvider));
50+
context.subscriptions.push(new VsCodeDebugInstrumentation(analyticsProvider));
4951

5052
}
5153

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { NONAME } from 'dns';
2+
import * as vscode from 'vscode';
3+
import { Disposable } from 'vscode-languageclient';
4+
import { AnalyticsProvider } from '../services/analyticsProvider';
5+
6+
export class VsCodeDebugInstrumentation implements vscode.Disposable{
7+
8+
private eventRegistration : Disposable;
9+
10+
constructor(private _analyticsProvider: AnalyticsProvider){
11+
12+
this.eventRegistration = vscode.debug.registerDebugAdapterTrackerFactory('*', {
13+
createDebugAdapterTracker(session: vscode.DebugSession) {
14+
return {
15+
onWillReceiveMessage: m => {
16+
},
17+
onDidSendMessage:
18+
m => {
19+
if (m.event ==='continued'){
20+
console.log('continued');
21+
_analyticsProvider.sendInsturmentationEvent(1);
22+
}
23+
if (m.event==='stopped'){
24+
_analyticsProvider.sendInsturmentationEvent(0);
25+
}
26+
}
27+
};
28+
}
29+
});
30+
31+
}
32+
dispose() {
33+
if (this.eventRegistration){
34+
this.eventRegistration.dispose();
35+
}
36+
}
37+
38+
39+
}
40+
41+

src/services/EditorHelper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class EditorHelper {
4141
{
4242
let doc: vscode.TextDocument | undefined = undefined;
4343

44-
if(!await utils.fileExits(workspaceUri))
44+
if(!await utils.fileExists(workspaceUri))
4545
{
4646
doc = await this.askAndOpenFromSourceControl(editorInfo);
4747
}

src/services/analyticsProvider.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { Logger } from "./logger";
66
import { Dictionary, momentJsDateParser } from "./utils";
77
import moment = require("moment");
88
import { integer } from "vscode-languageclient";
9+
import * as os from 'os';
10+
911

1012
export enum Impact
1113
{
@@ -349,6 +351,25 @@ export class AnalyticsProvider
349351
}
350352
return;
351353
}
354+
355+
public async sendInsturmentationEvent(event:integer): Promise<undefined>
356+
{
357+
try
358+
{
359+
const timestamp = Date.now().toString();
360+
const response = await this.send<undefined>(
361+
'POST',
362+
`/CodeAnalytics/instrumentation/event`,
363+
undefined,
364+
{event: event.toString(), machineName: os.hostname(),timestamp:timestamp });
365+
366+
return response;
367+
}
368+
catch(error){
369+
Logger.error('Failed to get error flow', error);
370+
}
371+
return;
372+
}
352373

353374

354375
private async send<TResponse>(method: string, relativePath: string, queryParams?: Dictionary<string, any>, body?: any): Promise<TResponse>

src/services/codeInvestigator.ts renamed to src/services/codeInspector.ts

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as vscode from 'vscode';
22

3-
import { DocumentInfoProvider, MethodInfo } from "./documentInfoProvider";
4-
import { Token, SymbolProvider } from './languages/symbolProvider';
3+
import { DocumentInfoProvider, MethodInfo } from './documentInfoProvider';
4+
import { SymbolProvider, SymbolTree } from './languages/symbolProvider';
5+
import { Token, TokenType } from './languages/tokens';
56

67
export interface Definition {
78
document: vscode.TextDocument
@@ -12,7 +13,7 @@ export type DefinitionWithTokens = Definition & {
1213
tokens: Token[]
1314
};
1415

15-
export class CodeInvestigator {
16+
export class CodeInspector {
1617

1718
public async getExecuteDefinitionMethodInfo(
1819
usageDocument: vscode.TextDocument,
@@ -63,4 +64,51 @@ export class CodeInvestigator {
6364
location,
6465
};
6566
}
67+
68+
public * getAllSymbolsOfKind(symbolTrees: SymbolTree[] | undefined, kind: vscode.SymbolKind): Generator<SymbolTree> {
69+
if(!symbolTrees) {
70+
return;
71+
}
72+
73+
for (const symbolTree of symbolTrees) {
74+
if(symbolTree.kind === kind) {
75+
yield symbolTree;
76+
}
77+
yield * this.getAllSymbolsOfKind(symbolTree.children as SymbolTree[] | undefined, kind);
78+
}
79+
}
80+
81+
public async derivesFrom(
82+
definition: DefinitionWithTokens,
83+
ancestorName: string,
84+
symbolProvider: SymbolProvider,
85+
findParentToken: (tokens: Token[], position: vscode.Position) => Token | undefined,
86+
): Promise<boolean> {
87+
const parentToken = findParentToken(definition.tokens, definition.location.range.start);
88+
if(!parentToken) {
89+
return false;
90+
}
91+
92+
if(parentToken.text === ancestorName) {
93+
return true;
94+
}
95+
96+
const parentInfo = await this.getTokensFromSymbolProvider(definition.document, parentToken.range.start, symbolProvider);
97+
if(!parentInfo) {
98+
return false;
99+
}
100+
101+
const parentSymbolTree = await symbolProvider.getSymbolTree(parentInfo.document);
102+
if(!parentSymbolTree) {
103+
return false;
104+
}
105+
106+
const parentDerivesFromAncestor = this.derivesFrom(
107+
parentInfo,
108+
ancestorName,
109+
symbolProvider,
110+
findParentToken,
111+
);
112+
return parentDerivesFromAncestor;
113+
}
66114
}

src/services/documentInfoProvider.ts

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { setInterval, clearInterval } from 'timers';
22
import * as vscode from 'vscode';
33
import { AnalyticsProvider, CodeObjectSummary, MethodCodeObjectSummary } from './analyticsProvider';
44
import { Logger } from "./logger";
5-
import { SymbolProvider, Token, TokenType } from './languages/symbolProvider';
5+
import { SymbolProvider } from './languages/symbolProvider';
6+
import { Token, TokenType } from './languages/tokens';
67
import { Dictionary, Future } from './utils';
78
import { EndpointInfo, SpanInfo, SymbolInfo, CodeObjectInfo } from './languages/extractors';
89
import { InstrumentationInfo } from './EditorHelper';
@@ -84,33 +85,38 @@ export class DocumentInfoProvider implements vscode.Disposable
8485
private async addOrUpdateDocumentInfo(doc: vscode.TextDocument): Promise<DocumentInfo | undefined>
8586
{
8687
const docRelativePath = doc.uri.toModulePath();
87-
if(!docRelativePath || !this.symbolProvider.supportsDocument(doc))
88+
if(!docRelativePath || !this.symbolProvider.supportsDocument(doc)) {
8889
return undefined;
90+
}
8991

9092
let document = this._documents[docRelativePath];
91-
if(!document)
92-
{
93+
if(!document) {
9394
document = this._documents[docRelativePath] = new DocumentInfoContainer();
9495
}
9596

9697
let latestVersionInfo = document.versions[doc.version];
97-
if(!latestVersionInfo)
98-
{
98+
if(!latestVersionInfo) {
9999
latestVersionInfo = document.versions[doc.version] = new Future<DocumentInfo>();
100100

101-
try
102-
{
101+
try {
103102
Logger.trace(`Starting building DocumentInfo for "${docRelativePath}" v${doc.version}`);
104-
const symbolInfos = await this.symbolProvider.getMethods(doc);
103+
const symbolTrees = await this.symbolProvider.getSymbolTree(doc);
104+
const symbolInfos = await this.symbolProvider.getMethods(doc, symbolTrees);
105105
const tokens = await this.symbolProvider.getTokens(doc);
106-
const endpoints = await this.symbolProvider.getEndpoints(doc, symbolInfos, tokens);
106+
const endpoints = await this.symbolProvider.getEndpoints(doc, symbolInfos, tokens, symbolTrees, this);
107107
const spans = await this.symbolProvider.getSpans(doc, symbolInfos, tokens);
108-
const methods = this.createMethodInfos(doc, symbolInfos, tokens, spans, endpoints);
109-
const summaries = new CodeObjectSummeryAccessor(await this.analyticsProvider.getSummaries(methods.map(s => s.idWithType).concat(endpoints.map(e => e.idWithType)).concat(spans.map(s => s.idWithType))));
110-
const lines = this.createLineInfos(doc, summaries, methods);
108+
const methodInfos = this.createMethodInfos(doc, symbolInfos, tokens, spans, endpoints);
109+
const summaries = new CodeObjectSummaryAccessor(
110+
await this.analyticsProvider.getSummaries(
111+
methodInfos.map(s => s.idWithType)
112+
.concat(endpoints.map(e => e.idWithType))
113+
.concat(spans.map(s => s.idWithType))
114+
)
115+
);
116+
const lines = this.createLineInfos(doc, summaries, methodInfos);
111117
latestVersionInfo.value = {
112118
summaries,
113-
methods,
119+
methods: methodInfos,
114120
lines,
115121
tokens,
116122
endpoints,
@@ -119,10 +125,9 @@ export class DocumentInfoProvider implements vscode.Disposable
119125
};
120126
Logger.trace(`Finished building DocumentInfo for "${docRelativePath}" v${doc.version}`);
121127
}
122-
catch(e)
123-
{
128+
catch(e) {
124129
latestVersionInfo.value = {
125-
summaries: new CodeObjectSummeryAccessor([]),
130+
summaries: new CodeObjectSummaryAccessor([]),
126131
methods: [],
127132
lines: [],
128133
tokens: [],
@@ -136,19 +141,21 @@ export class DocumentInfoProvider implements vscode.Disposable
136141

137142
return latestVersionInfo.value;
138143
}
139-
else
140-
{
144+
else {
141145
return await latestVersionInfo.wait();
142146
}
143147
}
144148

145-
private createMethodInfos(document: vscode.TextDocument, symbols: SymbolInfo[], tokens: Token[],
146-
spans: SpanInfo[], endpoints: EndpointInfo[]): MethodInfo[]
147-
{
149+
private createMethodInfos(
150+
document: vscode.TextDocument,
151+
symbols: SymbolInfo[],
152+
tokens: Token[],
153+
spans: SpanInfo[],
154+
endpoints: EndpointInfo[],
155+
): MethodInfo[] {
148156
let methods: MethodInfo[] = [];
149157

150-
for(let symbol of symbols)
151-
{
158+
for(let symbol of symbols) {
152159
const method = new MethodInfo(
153160
symbol.id,
154161
symbol.name,
@@ -164,22 +171,22 @@ export class DocumentInfoProvider implements vscode.Disposable
164171
methods.push(method);
165172

166173
const methodTokens = tokens.filter(t => symbol.range.contains(t.range.start));
167-
for(let token of methodTokens)
168-
{
174+
for(let token of methodTokens) {
169175
const name = token.text;// document.getText(token.range);
170176

171-
if((token.type === TokenType.method || token.type==TokenType.function)
172-
&& !method.nameRange
173-
&& name ===symbol.name)
174-
{
177+
if(
178+
(token.type === TokenType.method || token.type === TokenType.function || token.type === TokenType.member)
179+
&& !method.nameRange
180+
&& name === symbol.name
181+
) {
175182
method.nameRange = token.range;
176183
}
177184

178-
if(token.type == TokenType.parameter)
179-
{
180-
if(method.parameters.any(p => p.name == name))
185+
if(token.type === TokenType.parameter) {
186+
if(method.parameters.any(p => p.name === name)) {
181187
continue;
182-
188+
}
189+
183190
method.parameters.push({ name, range: token.range, token });
184191
}
185192
}
@@ -188,7 +195,7 @@ export class DocumentInfoProvider implements vscode.Disposable
188195
return methods;
189196
}
190197

191-
public createLineInfos(document: vscode.TextDocument, codeObjectSummaries: CodeObjectSummeryAccessor, methods: MethodInfo[]): LineInfo[]
198+
public createLineInfos(document: vscode.TextDocument, codeObjectSummaries: CodeObjectSummaryAccessor, methods: MethodInfo[]): LineInfo[]
192199
{
193200
const lineInfos: LineInfo[] = [];
194201
for(let method of methods)
@@ -258,15 +265,15 @@ class DocumentInfoContainer
258265

259266
export interface DocumentInfo
260267
{
261-
summaries: CodeObjectSummeryAccessor;
268+
summaries: CodeObjectSummaryAccessor;
262269
methods: MethodInfo[];
263270
lines: LineInfo[];
264271
tokens: Token[];
265272
endpoints: EndpointInfo[];
266273
spans: SpanInfo[];
267274
uri: vscode.Uri;
268275
}
269-
export class CodeObjectSummeryAccessor{
276+
export class CodeObjectSummaryAccessor{
270277
constructor(private _codeObejctSummeries: CodeObjectSummary[]){}
271278

272279
public get<T extends CodeObjectSummary>(type: { new(): T ;}, codeObjectId: string): T | undefined

0 commit comments

Comments
 (0)