Use the ast edge label when building the ast node label

The C PrintAST library now includes the edge name in the AST Viewer
tree.
This commit is contained in:
Andrew Eisenberg
2020-11-23 11:33:16 -08:00
parent 1886c0c9ec
commit 579df25be4
4 changed files with 76 additions and 5 deletions

View File

@@ -10,6 +10,7 @@
- Whenever the extension restarts, orphaned databases will be cleaned up. These are databases whose files are located inside of the extension's storage area, but are not imported into the workspace.
- After renaming a database, the database list is re-sorted. [#685](https://github.com/github/vscode-codeql/pull/685)
- Add a `codeQl.resultsDisplay.pageSize` setting to configure the number of results displayed in a single results view page. Increase the default page size from 100 to 200. [#686](https://github.com/github/vscode-codeql/pull/686)
- Update the AST Viewer to include edge labels (if available) in addition to the target node labels. So far, only C/C++ databases take advantage of this change. [#688](https://github.com/github/vscode-codeql/pull/688)
## 1.3.6 - 4 November 2020

View File

@@ -45,17 +45,18 @@ export default class AstBuilder {
const parentToChildren = new Map<BqrsId, BqrsId[]>();
const childToParent = new Map<BqrsId, BqrsId>();
const astOrder = new Map<BqrsId, number>();
const edgeLabels = new Map<BqrsId, string>();
const roots = [];
// Build up the parent-child relationships
edgeTuples.tuples.forEach(tuple => {
const [source, target, tupleType, orderValue] = tuple as [EntityValue, EntityValue, string, string];
const [source, target, tupleType, value] = tuple as [EntityValue, EntityValue, string, string];
const sourceId = source.id!;
const targetId = target.id!;
switch (tupleType) {
case 'semmle.order':
astOrder.set(targetId, Number(orderValue));
astOrder.set(targetId, Number(value));
break;
case 'semmle.label': {
@@ -65,6 +66,11 @@ export default class AstBuilder {
parentToChildren.set(sourceId, children = []);
}
children.push(targetId);
// ignore values that indicate a numeric order.
if (!Number.isFinite(Number(value))) {
edgeLabels.set(targetId, value);
}
break;
}
@@ -84,9 +90,13 @@ export default class AstBuilder {
break;
case 'semmle.label': {
// If an edge label exists, include it and separate from the node label using ':'
const nodeLabel = value ?? entity.label;
const edgeLabel = edgeLabels.get(id);
const label = [edgeLabel, nodeLabel].filter(e => e).join(': ');
const item = {
id,
label: value ?? entity.label,
label,
location: entity.url,
fileLocation: fileRangeFromURI(entity.url, this.db),
children: [] as ChildAstItem[],

View File

@@ -65,6 +65,66 @@ describe('AstBuilder', () => {
)).to.deep.eq(expectedRoots);
});
it('should build an AST child without edge label', async () => {
// just test one of the children to make sure that the structure is right
// this label should only come from the node, not the edge
const astBuilder = createAstBuilder();
const roots = await astBuilder.getRoots();
expect(roots[0].children[0].parent).to.eq(roots[0]);
// break the recursion
(roots[0].children[0] as any).parent = undefined;
(roots[0].children[0] as any).children = undefined;
const child = {
children: undefined,
fileLocation: undefined,
id: 26359,
label: 'params',
location: {
endColumn: 22,
endLine: 19,
startColumn: 5,
startLine: 19,
uri: 'file:/opt/src/arch/sandbox/lib/interrupts.c'
},
order: 0,
parent: undefined
};
expect(roots[0].children[0]).to.deep.eq(child);
});
it('should build an AST child with edge label', async () => {
// just test one of the children to make sure that the structure is right
// this label should only come from both the node and the edge
const astBuilder = createAstBuilder();
const roots = await astBuilder.getRoots();
expect(roots[0].children[1].parent).to.eq(roots[0]);
// break the recursion
(roots[0].children[1] as any).parent = undefined;
(roots[0].children[1] as any).children = undefined;
const child = {
children: undefined,
fileLocation: undefined,
id: 26367,
label: 'body: [Block] { ... }',
location: {
endColumn: 1,
endLine: 22,
startColumn: 1,
startLine: 20,
uri: 'file:/opt/src/arch/sandbox/lib/interrupts.c'
},
order: 2,
parent: undefined
};
expect(roots[0].children[1]).to.deep.eq(child);
});
it('should fail when graphProperties are not correct', async () => {
overrides.graphProperties = {
tuples: [

View File

@@ -28,7 +28,7 @@
}
},
"semmle.label",
""
"params"
],
[
{
@@ -406,7 +406,7 @@
}
},
"semmle.label",
"params"
"1234"
],
[
{