зеркало из https://github.com/microsoft/gather.git
Formatting: Formatted code with Prettier
This commit is contained in:
Родитель
c00af26b8c
Коммит
9ca778fe95
|
@ -9,7 +9,6 @@ import { SliceConfiguration } from './slice-config';
|
|||
* For caching to work, statements must be annotated with a cell's ID and execution count.
|
||||
*/
|
||||
export class DataflowAnalyzer {
|
||||
|
||||
constructor(sliceConfiguration?: SliceConfiguration) {
|
||||
this._sliceConfiguration = sliceConfiguration || [];
|
||||
}
|
||||
|
@ -56,7 +55,6 @@ export class DataflowAnalyzer {
|
|||
sliceConfiguration?: SliceConfiguration,
|
||||
namesDefined?: StringSet
|
||||
): DataflowAnalysisResult {
|
||||
|
||||
sliceConfiguration = sliceConfiguration || [];
|
||||
let symbolTable: SymbolTable = { moduleNames: new StringSet() };
|
||||
const workQueue: Block[] = cfg.blocks.reverse();
|
||||
|
@ -116,7 +114,8 @@ export class DataflowAnalyzer {
|
|||
!definedHere.items.some(
|
||||
def =>
|
||||
def.level == ReferenceType.DEFINITION &&
|
||||
def.name == use.name && sameLocation(def.location, use.location)
|
||||
def.name == use.name &&
|
||||
sameLocation(def.location, use.location)
|
||||
)
|
||||
) {
|
||||
statementRefs[ReferenceType.USE].add(use);
|
||||
|
@ -319,8 +318,11 @@ export class DataflowAnalyzer {
|
|||
})
|
||||
.filter(n => n != undefined)
|
||||
);
|
||||
let undefinedRefs = this.analyze(defCfg, this._sliceConfiguration, argNames)
|
||||
.undefinedRefs;
|
||||
let undefinedRefs = this.analyze(
|
||||
defCfg,
|
||||
this._sliceConfiguration,
|
||||
argNames
|
||||
).undefinedRefs;
|
||||
uses = undefinedRefs.filter(r => r.level == ReferenceType.USE);
|
||||
break;
|
||||
case ast.CLASS:
|
||||
|
@ -490,7 +492,10 @@ class DefAnnotationListener implements ast.IWalkListener {
|
|||
* Tree walk listener for collecting names used in function call.
|
||||
*/
|
||||
class CallNamesListener implements ast.IWalkListener {
|
||||
constructor(sliceConfiguration: SliceConfiguration, statement: ast.ISyntaxNode) {
|
||||
constructor(
|
||||
sliceConfiguration: SliceConfiguration,
|
||||
statement: ast.ISyntaxNode
|
||||
) {
|
||||
this._sliceConfiguration = sliceConfiguration;
|
||||
this._statement = statement;
|
||||
}
|
||||
|
@ -501,7 +506,6 @@ class CallNamesListener implements ast.IWalkListener {
|
|||
ancestors: ast.ISyntaxNode[]
|
||||
) {
|
||||
if (type == ast.CALL) {
|
||||
|
||||
let callNode = node as ast.ICall;
|
||||
let functionNameNode: ast.ISyntaxNode;
|
||||
let functionName: string;
|
||||
|
@ -509,7 +513,7 @@ class CallNamesListener implements ast.IWalkListener {
|
|||
functionNameNode = callNode.func.name;
|
||||
functionName = functionNameNode.toString();
|
||||
} else {
|
||||
functionNameNode = (callNode.func as ast.IName);
|
||||
functionNameNode = callNode.func as ast.IName;
|
||||
functionName = functionNameNode.id;
|
||||
}
|
||||
|
||||
|
@ -530,13 +534,13 @@ class CallNamesListener implements ast.IWalkListener {
|
|||
if (callNode.func.type == ast.DOT) {
|
||||
let skipObject = false;
|
||||
for (let skipRule of skipRules) {
|
||||
if (skipRule.doesNotModify.indexOf("OBJECT") !== -1) {
|
||||
if (skipRule.doesNotModify.indexOf('OBJECT') !== -1) {
|
||||
skipObject = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!skipObject && callNode.func.value !== undefined) {
|
||||
this._subtreesToProcess.push(callNode.func.value);
|
||||
this._subtreesToProcess.push(callNode.func.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,11 +549,14 @@ class CallNamesListener implements ast.IWalkListener {
|
|||
let skipArg = false;
|
||||
for (let skipRule of skipRules) {
|
||||
for (let skipSpec of skipRule.doesNotModify) {
|
||||
if ((typeof skipSpec === 'number') && skipSpec === i) {
|
||||
if (typeof skipSpec === 'number' && skipSpec === i) {
|
||||
skipArg = true;
|
||||
break;
|
||||
} else if (typeof skipSpec === 'string') {
|
||||
if (skipSpec === 'ARGUMENTS' || (arg.keyword && (arg.keyword as ast.IName).id === skipSpec)) {
|
||||
if (
|
||||
skipSpec === 'ARGUMENTS' ||
|
||||
(arg.keyword && (arg.keyword as ast.IName).id === skipSpec)
|
||||
) {
|
||||
skipArg = true;
|
||||
break;
|
||||
}
|
||||
|
@ -571,12 +578,11 @@ class CallNamesListener implements ast.IWalkListener {
|
|||
level: ReferenceType.UPDATE,
|
||||
name: (node as ast.IName).id,
|
||||
location: node.location,
|
||||
statement: this._statement
|
||||
statement: this._statement,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -649,16 +655,12 @@ let DEPENDENCY_RULES = [
|
|||
// "from" depends on all reference types in "to"
|
||||
{
|
||||
from: ReferenceType.USE,
|
||||
to: [
|
||||
ReferenceType.UPDATE,
|
||||
ReferenceType.DEFINITION,
|
||||
],
|
||||
}, {
|
||||
to: [ReferenceType.UPDATE, ReferenceType.DEFINITION],
|
||||
},
|
||||
{
|
||||
from: ReferenceType.UPDATE,
|
||||
to: [
|
||||
ReferenceType.DEFINITION
|
||||
]
|
||||
}
|
||||
to: [ReferenceType.DEFINITION],
|
||||
},
|
||||
];
|
||||
|
||||
let TYPES_WITH_DEPENDENCIES = DEPENDENCY_RULES.map(r => r.from);
|
||||
|
@ -672,17 +674,12 @@ let KILL_RULES = [
|
|||
// it neither depends on initializations or updates, nor clobbers them.
|
||||
{
|
||||
level: ReferenceType.DEFINITION,
|
||||
kills: [
|
||||
ReferenceType.DEFINITION,
|
||||
ReferenceType.UPDATE
|
||||
],
|
||||
}, {
|
||||
kills: [ReferenceType.DEFINITION, ReferenceType.UPDATE],
|
||||
},
|
||||
{
|
||||
level: ReferenceType.UPDATE,
|
||||
kills: [
|
||||
ReferenceType.DEFINITION,
|
||||
ReferenceType.UPDATE
|
||||
],
|
||||
}
|
||||
kills: [ReferenceType.DEFINITION, ReferenceType.UPDATE],
|
||||
},
|
||||
];
|
||||
|
||||
function updateDefsForLevel(
|
||||
|
|
|
@ -138,9 +138,7 @@ export class ExecutionLogSlicer {
|
|||
}
|
||||
|
||||
return this._executionLog
|
||||
.filter(
|
||||
execution => execution.cell.persistentId == cell.persistentId
|
||||
)
|
||||
.filter(execution => execution.cell.persistentId == cell.persistentId)
|
||||
.filter(execution => execution.cell.executionCount != undefined)
|
||||
.map(execution => {
|
||||
// Build the program up to that cell.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Default rules are listed in {@code schema/plugin.json}.
|
||||
*/
|
||||
export type SliceConfiguration = {
|
||||
objectName?: string,
|
||||
functionName: string,
|
||||
doesNotModify: (string|Number)[]
|
||||
}[];
|
||||
objectName?: string;
|
||||
functionName: string;
|
||||
doesNotModify: (string | Number)[];
|
||||
}[];
|
||||
|
|
|
@ -50,7 +50,6 @@ const extension: JupyterLabPlugin<void> = {
|
|||
|
||||
/**
|
||||
* Extension for tracking sequences of cells executed in a notebook.
|
||||
* TODO(andrewhead): have an execution stamp that includes the kernel that executed a cell... (requires insulation in program builder)
|
||||
* TODO(andrewhead): can we run the analysis on the backend with a web-worker (specifically, def-use?)
|
||||
*/
|
||||
export class CodeGatheringExtension
|
||||
|
@ -67,10 +66,10 @@ export class CodeGatheringExtension
|
|||
this._notebooks = notebooks;
|
||||
this._gatherModelRegistry = gatherModelRegistry;
|
||||
settingRegistry.get('nbgather:plugin', 'rules').then(data => {
|
||||
if (JSONExt.isArray(data.composite)) {
|
||||
let dataCompositeObject = data.composite as JSONArray;
|
||||
this._sliceConfiguration = dataCompositeObject as SliceConfiguration;
|
||||
}
|
||||
if (JSONExt.isArray(data.composite)) {
|
||||
let dataCompositeObject = data.composite as JSONArray;
|
||||
this._sliceConfiguration = dataCompositeObject as SliceConfiguration;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -87,7 +86,9 @@ export class CodeGatheringExtension
|
|||
* executed cells and the state of the gather UI.
|
||||
*/
|
||||
let notebookModel = notebookContext.model;
|
||||
let executionLog = new ExecutionLogSlicer(new DataflowAnalyzer(this._sliceConfiguration));
|
||||
let executionLog = new ExecutionLogSlicer(
|
||||
new DataflowAnalyzer(this._sliceConfiguration)
|
||||
);
|
||||
let gatherModel = new GatherModel(executionLog);
|
||||
new ExecutionLogger(gatherModel);
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ export class LogCell extends AbstractCell {
|
|||
constructor(data: {
|
||||
id?: string;
|
||||
executionCount?: number;
|
||||
persistentId?: string,
|
||||
persistentId?: string;
|
||||
executionEventId?: string;
|
||||
hasError?: boolean;
|
||||
text?: string;
|
||||
|
@ -218,10 +218,10 @@ export class LabCell extends AbstractCell {
|
|||
}
|
||||
|
||||
get persistentId(): string {
|
||||
if (!this._model.metadata.has("persistent_id")) {
|
||||
this._model.metadata.set("persistent_id", UUID.uuid4());
|
||||
if (!this._model.metadata.has('persistent_id')) {
|
||||
this._model.metadata.set('persistent_id', UUID.uuid4());
|
||||
}
|
||||
return this._model.metadata.get("persistent_id") as string;
|
||||
return this._model.metadata.get('persistent_id') as string;
|
||||
}
|
||||
|
||||
get executionEventId(): string {
|
||||
|
|
|
@ -90,7 +90,7 @@ function _loadExecutionFromJson(executionJson: JSONObject): CellExecution {
|
|||
}
|
||||
|
||||
function _getOutputs(json: JSONObject): nbformat.IOutput[] {
|
||||
if (!json.hasOwnProperty("outputs") || !(JSONExt.isArray(json["outputs"]))) {
|
||||
if (!json.hasOwnProperty('outputs') || !JSONExt.isArray(json['outputs'])) {
|
||||
log('Could not find outputs in object ' + json);
|
||||
return null;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ function _loadExecutionFromJson(executionJson: JSONObject): CellExecution {
|
|||
text,
|
||||
persistentId,
|
||||
executionEventId,
|
||||
outputs
|
||||
outputs,
|
||||
});
|
||||
return new CellExecution(cell, executionTime);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ interface CellExecutionJson extends JSONObject {
|
|||
|
||||
interface CellJson extends JSONObject {
|
||||
id: string;
|
||||
persistentId: string,
|
||||
persistentId: string;
|
||||
executionEventId: string;
|
||||
executionCount: number;
|
||||
hasError: boolean;
|
||||
|
|
|
@ -12,7 +12,6 @@ import {
|
|||
import { Set, StringSet } from '../analysis/slice/set';
|
||||
import { SliceConfiguration } from '../analysis/slice/slice-config';
|
||||
|
||||
|
||||
describe('detects dataflow dependencies', () => {
|
||||
function analyze(...codeLines: string[]): Set<IDataflow> {
|
||||
let code = codeLines.concat('').join('\n'); // add newlines to end of every line.
|
||||
|
@ -167,7 +166,10 @@ describe('getDefs', () => {
|
|||
.items;
|
||||
}
|
||||
|
||||
function getDefNamesFromStatement(code: string, sliceConfiguration?: SliceConfiguration) {
|
||||
function getDefNamesFromStatement(
|
||||
code: string,
|
||||
sliceConfiguration?: SliceConfiguration
|
||||
) {
|
||||
return getDefsFromStatement(code, sliceConfiguration).map(def => def.name);
|
||||
}
|
||||
|
||||
|
@ -285,48 +287,43 @@ describe('getDefs', () => {
|
|||
});
|
||||
|
||||
describe('; given a slice config', () => {
|
||||
|
||||
it('can ignore all arguments', () => {
|
||||
let defs = getDefsFromStatement(
|
||||
'func(a, b, c)',
|
||||
[{
|
||||
let defs = getDefsFromStatement('func(a, b, c)', [
|
||||
{
|
||||
functionName: 'func',
|
||||
doesNotModify: ["ARGUMENTS"],
|
||||
}]
|
||||
);
|
||||
doesNotModify: ['ARGUMENTS'],
|
||||
},
|
||||
]);
|
||||
expect(defs).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('can ignore the object functions are called on', () => {
|
||||
let defs = getDefsFromStatement(
|
||||
'obj.func()',
|
||||
[{
|
||||
let defs = getDefsFromStatement('obj.func()', [
|
||||
{
|
||||
functionName: 'func',
|
||||
doesNotModify: ["OBJECT"],
|
||||
}]
|
||||
);
|
||||
doesNotModify: ['OBJECT'],
|
||||
},
|
||||
]);
|
||||
expect(defs).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('can ignore positional arguments a function is called with', () => {
|
||||
let defs = getDefNamesFromStatement(
|
||||
'func(a)',
|
||||
[{
|
||||
let defs = getDefNamesFromStatement('func(a)', [
|
||||
{
|
||||
functionName: 'func',
|
||||
doesNotModify: [0],
|
||||
}]
|
||||
);
|
||||
},
|
||||
]);
|
||||
expect(defs).to.not.include('a');
|
||||
});
|
||||
|
||||
it('can ignore keyword arguments a function is called with', () => {
|
||||
let defs = getDefNamesFromStatement(
|
||||
'func(a=var)',
|
||||
[{
|
||||
let defs = getDefNamesFromStatement('func(a=var)', [
|
||||
{
|
||||
functionName: 'func',
|
||||
doesNotModify: ['a'],
|
||||
}]
|
||||
);
|
||||
},
|
||||
]);
|
||||
expect(defs).to.deep.equal([]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -49,41 +49,46 @@ export function log(eventName: string, data?: any) {
|
|||
};
|
||||
|
||||
if (_settingRegistry != undefined || _settingRegistry != null) {
|
||||
|
||||
_settingRegistry.get('nbgather:plugin', 'loggingEnabled').then(loggingEnabled => {
|
||||
if ((typeof(loggingEnabled.composite) === 'boolean') && loggingEnabled.composite) {
|
||||
_settingRegistry
|
||||
.get('nbgather:plugin', 'loggingEnabled')
|
||||
.then(loggingEnabled => {
|
||||
if (
|
||||
typeof loggingEnabled.composite === 'boolean' &&
|
||||
loggingEnabled.composite
|
||||
) {
|
||||
_settingRegistry
|
||||
.get('nbgather:plugin', 'loggingId')
|
||||
.then(loggingId => {
|
||||
if (typeof loggingId.composite === 'string') {
|
||||
postData.loggingId = loggingId.composite as string;
|
||||
|
||||
_settingRegistry.get('nbgather:plugin', 'loggingId').then(loggingId => {
|
||||
if (typeof(loggingId.composite) === 'string') {
|
||||
postData.loggingId = loggingId.composite as string;
|
||||
|
||||
// Poll for additional data from each state poller.
|
||||
for (let poller of _statePollers) {
|
||||
let pollData = poller.poll();
|
||||
for (let k in pollData) {
|
||||
if (pollData.hasOwnProperty(k)) {
|
||||
postData[k] = pollData[k];
|
||||
// Poll for additional data from each state poller.
|
||||
for (let poller of _statePollers) {
|
||||
let pollData = poller.poll();
|
||||
for (let k in pollData) {
|
||||
if (pollData.hasOwnProperty(k)) {
|
||||
postData[k] = pollData[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is any sensitive data to be logged, it should first be cleaned through a
|
||||
// `toJSON` method defined on a class, or manually before passing it into this method.
|
||||
// Earlier, we used the replacer argument to JSON.stringify, but it takes too much time
|
||||
// to apply replacers to every value in the resulting JSON.
|
||||
postData.data = JSON.stringify(postData.data);
|
||||
|
||||
// Submit data to logger endpoint.
|
||||
$.ajax(LOG_ENDPOINT + '/log', {
|
||||
data: postData,
|
||||
method: 'POST',
|
||||
error: (_: any, textStatus: string, errorThrown: string) => {
|
||||
console.error('Failed to log', textStatus, errorThrown);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// If there is any sensitive data to be logged, it should first be cleaned through a
|
||||
// `toJSON` method defined on a class, or manually before passing it into this method.
|
||||
// Earlier, we used the replacer argument to JSON.stringify, but it takes too much time
|
||||
// to apply replacers to every value in the resulting JSON.
|
||||
postData.data = JSON.stringify(postData.data);
|
||||
|
||||
// Submit data to logger endpoint.
|
||||
$.ajax(LOG_ENDPOINT + '/log', {
|
||||
data: postData,
|
||||
method: 'POST',
|
||||
error: (_: any, textStatus: string, errorThrown: string) => {
|
||||
console.error('Failed to log', textStatus, errorThrown);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ import { CodeVersion } from '../codeversion';
|
|||
import { GatherState } from '../../model';
|
||||
import { IRevisionModel } from './model';
|
||||
import { OutputArea, OutputAreaModel } from '@jupyterlab/outputarea';
|
||||
import { RenderMimeRegistry, standardRendererFactories } from '@jupyterlab/rendermime';
|
||||
import {
|
||||
RenderMimeRegistry,
|
||||
standardRendererFactories,
|
||||
} from '@jupyterlab/rendermime';
|
||||
|
||||
// HTML element classes for rendered revisions
|
||||
const REVISION_CLASS = 'jp-Revision';
|
||||
|
@ -28,11 +31,15 @@ class OutputRenderer {
|
|||
render(outputs: nbformat.IOutput[]): HTMLElement {
|
||||
let outputArea = new OutputArea({
|
||||
model: new OutputAreaModel({ values: outputs, trusted: false }),
|
||||
rendermime: new RenderMimeRegistry({ initialFactories: standardRendererFactories })
|
||||
});
|
||||
outputArea.node.querySelectorAll('.jp-OutputArea-prompt').forEach((promptNode) => {
|
||||
promptNode.remove();
|
||||
rendermime: new RenderMimeRegistry({
|
||||
initialFactories: standardRendererFactories,
|
||||
}),
|
||||
});
|
||||
outputArea.node
|
||||
.querySelectorAll('.jp-OutputArea-prompt')
|
||||
.forEach(promptNode => {
|
||||
promptNode.remove();
|
||||
});
|
||||
outputArea.addClass(REVISION_OUTPUT_CLASS);
|
||||
return outputArea.node;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче