Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extensions/ql-vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
16 changes: 13 additions & 3 deletions extensions/ql-vscode/src/contextual/astBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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': {
Expand All @@ -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))) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're in the semmle.label case rather than semmle.order, isn't it reasonable to accept a number as the edge label?

Copy link
Copy Markdown
Contributor Author

@aeisenberg aeisenberg Nov 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you get to line 71, you are always looking at semmle.label since this is a switch statement.

If we accept a number as an edge label here, then we get confusing labels in the nodes of the ast viewer tree.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the AST viewer already numbers children?

edgeLabels.set(targetId, value);
}
break;
}

Expand All @@ -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[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}
},
"semmle.label",
""
"params"
],
[
{
Expand Down Expand Up @@ -406,7 +406,7 @@
}
},
"semmle.label",
"params"
"1234"
],
[
{
Expand Down