From 1a2f7faaca9b090217a5b3bc7699db32aeef3173 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Mon, 23 Mar 2020 23:33:42 -0400 Subject: [PATCH 01/21] [DebuggerV2] Display source code --- .../debugger_component.css | 11 +- .../debugger_component.ng.html | 5 + .../debugger_component.ts | 5 +- .../debugger_container.ts | 11 +- .../tf_debugger_v2_plugin/debugger_module.ts | 2 + .../views/source_code/BUILD | 26 +++ .../source_code/source_code_component.css | 0 .../source_code/source_code_component.ng.html | 20 +++ .../source_code/source_code_component.ts | 40 +++++ .../views/source_code/source_code_module.ts | 26 +++ .../views/stack_trace/BUILD | 1 + .../stack_trace/stack_trace_component.css | 2 + .../stack_trace/stack_trace_component.ng.html | 5 +- .../stack_trace/stack_trace_component.ts | 9 +- .../stack_trace/stack_trace_container.ts | 13 ++ .../views/stack_trace/stack_trace_module.ts | 6 +- tensorboard/webapp/BUILD | 2 + tensorboard/webapp/index.uninlined.html | 2 + yarn.lock | 149 ++---------------- 19 files changed, 191 insertions(+), 144 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css index 543ae34b0e..125b32f92f 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css @@ -14,6 +14,7 @@ limitations under the License. ==============================================================================*/ .bottom-section { + /* float: bottom; */ width: 100%; } @@ -28,10 +29,18 @@ tf-debugger-v2-alerts { width: 200px; } +source-code-component { + display: inline-block; + height: 100%; + width: 70%; +} + tf-debugger-v2-stack-trace { + display: inline-block; + width: 30%; /* TODO(cais): Once code-editor component is added to the left, replace the `float` with a linear layout. */ - float: right; + /* float: right; */ } tf-debugger-v2-timeline { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html index 3b13d4a0cb..93b80f47dd 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html @@ -26,6 +26,11 @@
+ +
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts index 8ccb00a3e7..4eef6f6392 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; -import {DebuggerRunListing} from './store/debugger_types'; +import {DebuggerRunListing, SourceFileContent} from './store/debugger_types'; @Component({ selector: 'debugger-component', @@ -30,4 +30,7 @@ export class DebuggerComponent { @Input() activeRunId: string | null = null; + + @Input() + focusedSourceFileContent: SourceFileContent | null = null; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts index 83aa477c8b..ba26e6e39e 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts @@ -17,7 +17,11 @@ import {createSelector, select, Store} from '@ngrx/store'; import {State} from './store/debugger_types'; import {debuggerLoaded} from './actions'; -import {getActiveRunId, getDebuggerRunListing} from './store'; +import { + getActiveRunId, + getDebuggerRunListing, + getFocusedSourceFileContent, +} from './store'; /** @typehack */ import * as _typeHackRxjs from 'rxjs'; @@ -28,6 +32,7 @@ import {getActiveRunId, getDebuggerRunListing} from './store'; [runs]="runs$ | async" [runIds]="runsIds$ | async" [activeRunId]="activeRunId$ | async" + [focusedSourceFileContent]="focusedSourceFileContent$ | async" > `, }) @@ -45,6 +50,10 @@ export class DebuggerContainer implements OnInit { readonly activeRunId$ = this.store.pipe(select(getActiveRunId)); + readonly focusedSourceFileContent$ = this.store.pipe( + select(getFocusedSourceFileContent) + ); + constructor(private readonly store: Store) {} ngOnInit(): void { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts index 01a2172755..0ca8137e59 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts @@ -26,6 +26,7 @@ import {reducers} from './store/debugger_reducers'; import {DEBUGGER_FEATURE_KEY} from './store/debugger_types'; import {AlertsModule} from './views/alerts/alerts_module'; import {InactiveModule} from './views/inactive/inactive_module'; +import {SourceCodeModule} from './views/source_code/source_code_module'; import {StackTraceModule} from './views/stack_trace/stack_trace_module'; import {TimelineModule} from './views/timeline/timeline_module'; import {PluginRegistryModule} from '../../../webapp/plugins/plugin_registry_module'; @@ -36,6 +37,7 @@ import {PluginRegistryModule} from '../../../webapp/plugins/plugin_registry_modu AlertsModule, CommonModule, InactiveModule, + SourceCodeModule, StackTraceModule, Tfdbg2ServerDataSourceModule, TimelineModule, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD index a09fcaab81..c7fa2ea840 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD @@ -1,9 +1,35 @@ package(default_visibility = ["//tensorboard:internal"]) +load("@npm_angular_bazel//:index.bzl", "ng_module") load("//tensorboard/defs:defs.bzl", "tf_ts_library") licenses(["notice"]) # Apache 2.0 +ng_module( + name = "source_code", + srcs = [ + "source_code_component.ts", + "source_code_module.ts", + ], + assets = [ + "source_code_component.css", + "source_code_component.ng.html", + ], + deps = [ + ":load_monaco", + # TODO(cais): Clean up. + # "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:tf_types", + # "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", + "@npm//@angular/common", + "@npm//@angular/core", + "@npm//@ngrx/store", + "@npm//rxjs", + ], +) + + tf_ts_library( name = "load_monaco", srcs = [ diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html new file mode 100644 index 0000000000..6d2afbb394 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html @@ -0,0 +1,20 @@ + + +
+ Monaco Goes Here +
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts new file mode 100644 index 0000000000..1ec7fb3499 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -0,0 +1,40 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +import {Component, Input, OnInit} from '@angular/core'; + +import {loadMonaco, WindowWithRequireAndMonaco} from '../source_code/load_monaco_shim'; + +const windowWithRequireAndMonaco: WindowWithRequireAndMonaco = window; + +@Component({ + selector: 'source-code-component', + templateUrl: './source_code_component.ng.html', + styleUrls: ['./source_code_component.css'], +}) +export class SourceCodeComponent implements OnInit { + @Input() + lines: string[] | null = null; // TODO(cais): Add spinner for `null`. + + // @Input() + // focusedLineno: number | null = null; + + async ngOnInit(): Promise { + console.log('SourceCodeComponent.ngOnInit(): lines=', this.lines); // DEBUG + if (windowWithRequireAndMonaco.monaco === undefined) { + await loadMonaco(); + console.log('Done loading monaco:', windowWithRequireAndMonaco.monaco); + } + } +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts new file mode 100644 index 0000000000..aa494ce5bf --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts @@ -0,0 +1,26 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; + +import {SourceCodeComponent} from './source_code_component'; + +@NgModule({ + declarations: [SourceCodeComponent], + imports: [CommonModule], + exports: [SourceCodeComponent], +}) +export class SourceCodeModule {} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD index da3d1c3c05..9874bb0b8f 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD @@ -18,6 +18,7 @@ ng_module( deps = [ "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code", "@npm//@angular/common", "@npm//@angular/core", "@npm//@ngrx/store", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css index 084219754c..272bcb6667 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css @@ -42,9 +42,11 @@ limitations under the License. } .stack-frame-lineno { + cursor: pointer; display: inline-block; max-width: 80px; text-align: left; + text-decoration: underline; width: 80px; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html index 6eaef88e93..0c8a194a7a 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html @@ -44,7 +44,10 @@
-
+
Line {{ stackFrameForDisplay.lineno }}:
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts index 745aab2e36..ad099200a5 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts @@ -12,7 +12,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -import {Component, Input} from '@angular/core'; +import {Component, Input, EventEmitter, Output} from '@angular/core'; export interface StackFrameForDisplay { host_name: string; @@ -30,4 +30,11 @@ export interface StackFrameForDisplay { export class StackTraceComponent { @Input() stackFramesForDisplay: StackFrameForDisplay[] | null = null; + + @Output() + onSourceLineClicked = new EventEmitter<{ + host_name: string, + file_path: string, + lineno: number, + }>(); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts index 8015c5baa5..d03ea2b374 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts @@ -17,16 +17,19 @@ import {createSelector, select, Store} from '@ngrx/store'; import {State} from '../../store/debugger_types'; +import {sourceLineFocused} from '../../actions'; import {getFocusedExecutionStackFrames} from '../../store'; import {StackFrameForDisplay} from './stack_trace_component'; /** @typehack */ import * as _typeHackRxjs from 'rxjs'; + @Component({ selector: 'tf-debugger-v2-stack-trace', template: ` `, }) @@ -59,4 +62,14 @@ export class StackTraceContainer { ); constructor(private readonly store: Store) {} + + onSourceLineClicked(args: { + host_name: string, + file_path: string, + lineno: number, + }) { + console.log( + 'StackTraceContainer.onSourceLineClicked: args:', args); // DEBUG + this.store.dispatch(sourceLineFocused({sourceLineSpec: args})); + } } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts index ba4e86ff46..16034add18 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts @@ -16,12 +16,16 @@ limitations under the License. import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; +import {SourceCodeModule} from '../source_code/source_code_module'; import {StackTraceComponent} from './stack_trace_component'; import {StackTraceContainer} from './stack_trace_container'; @NgModule({ declarations: [StackTraceComponent, StackTraceContainer], - imports: [CommonModule], + imports: [ + CommonModule, + SourceCodeModule, + ], exports: [StackTraceContainer], }) export class StackTraceModule {} diff --git a/tensorboard/webapp/BUILD b/tensorboard/webapp/BUILD index 73d04615b5..9336ce2f35 100644 --- a/tensorboard/webapp/BUILD +++ b/tensorboard/webapp/BUILD @@ -111,6 +111,8 @@ tf_web_library( deps = [ ":tb_webapp", "//tensorboard/components:ng_polymer_lib_binary", + # TODO(cais): Add copybara rule. + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/monaco:requirejs", ], ) diff --git a/tensorboard/webapp/index.uninlined.html b/tensorboard/webapp/index.uninlined.html index 9dc2663ad4..89f3f5c72e 100644 --- a/tensorboard/webapp/index.uninlined.html +++ b/tensorboard/webapp/index.uninlined.html @@ -24,6 +24,8 @@ + + diff --git a/yarn.lock b/yarn.lock index d30f945922..0fbcf94316 100644 --- a/yarn.lock +++ b/yarn.lock @@ -493,11 +493,6 @@ JSONStream@^1.3.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - accepts@~1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -622,19 +617,11 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.0.3, aproba@^1.1.1: +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@~1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1144,11 +1131,6 @@ connect@^3.6.0: parseurl "~1.3.3" utils-merge "1.0.1" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -1279,11 +1261,6 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -1318,11 +1295,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1333,11 +1305,6 @@ dependency-graph@^0.7.2: resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.7.2.tgz#91db9de6eb72699209d88aea4c1fd5221cac1c49" integrity sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ== -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -1806,20 +1773,6 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - genfun@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" @@ -1942,11 +1895,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -2055,7 +2003,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -2112,7 +2060,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@1.3.5, ini@~1.3.0: +ini@1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -2922,15 +2870,6 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -needle@^2.2.1: - version "2.3.3" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.3.tgz#a041ad1d04a871b0ebb666f40baaf1fb47867117" - integrity sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -2966,30 +2905,6 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - -nopt@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" - integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -3044,7 +2959,7 @@ npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: semver "^5.6.0" validate-npm-package-name "^3.0.0" -npm-packlist@^1.1.12, npm-packlist@^1.1.6: +npm-packlist@^1.1.12: version "1.4.8" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== @@ -3091,16 +3006,6 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - null-check@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" @@ -3116,11 +3021,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" @@ -3232,7 +3132,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4, osenv@^0.1.5: +osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -3561,16 +3461,6 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - read-package-json@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" @@ -3609,7 +3499,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -3788,7 +3678,7 @@ rimraf@3.0.0: dependencies: glob "^7.1.3" -rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: +rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -3863,11 +3753,6 @@ saucelabs@^1.5.0: dependencies: https-proxy-agent "^2.2.1" -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - selenium-webdriver@^4.0.0-alpha.1: version "4.0.0-alpha.7" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.7.tgz#e3879d8457fd7ad8e4424094b7dc0540d99e6797" @@ -3884,7 +3769,7 @@ semver-intersect@1.4.0: dependencies: semver "^5.0.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -3899,7 +3784,7 @@ semver@6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -4222,7 +4107,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -4309,11 +4194,6 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - supports-color@^3.1.2: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" @@ -4333,7 +4213,7 @@ symbol-observable@1.2.0: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== -tar@^4.4.2, tar@^4.4.8: +tar@^4.4.8: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -4685,13 +4565,6 @@ which@^1.2.1, which@^1.2.9, which@^1.3.0, which@^1.3.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" From f514b425db36087d3e45fb3b571d00e5ada9b44f Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 24 Mar 2020 16:14:19 -0400 Subject: [PATCH 02/21] Add SourceCodeComponent and SourceFileComponent monaco editor appears, but needs more styling --- .../debugger_v2/tf_debugger_v2_plugin/BUILD | 2 + .../debugger_component.css | 5 ++- .../debugger_component.ng.html | 6 +-- .../debugger_component.ts | 3 -- .../debugger_container.ts | 11 +---- .../debugger_container_test.ts | 2 + .../tf_debugger_v2_plugin/debugger_module.ts | 4 +- .../tf_debugger_v2_plugin/views/alerts/BUILD | 1 + .../views/alerts/alerts_container_test.ts | 2 + .../views/source_code/BUILD | 1 - .../source_code/source_code_component.css | 9 ++++ .../source_code/source_code_component.ng.html | 6 +-- .../source_code/source_code_component.ts | 41 +++++++++++++++++-- .../views/source_files/BUILD | 27 ++++++++++++ .../source_files/source_files_component.css | 10 +++++ .../source_files_component.ng.html | 27 ++++++++++++ .../source_files/source_files_component.ts | 27 ++++++++++++ .../source_files/source_files_container.ts | 37 +++++++++++++++++ .../views/source_files/source_files_module.ts | 31 ++++++++++++++ 19 files changed, 223 insertions(+), 29 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD index 2afa322003..b8dc693cbc 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD @@ -27,6 +27,7 @@ ng_module( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", "//tensorboard/webapp/plugins:plugin_registry", @@ -54,6 +55,7 @@ tf_ts_library( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", "//tensorboard/webapp/angular:expect_angular_core_testing", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css index 125b32f92f..b73186f1b8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css @@ -14,7 +14,7 @@ limitations under the License. ==============================================================================*/ .bottom-section { - /* float: bottom; */ + height: 360px; width: 100%; } @@ -29,9 +29,10 @@ tf-debugger-v2-alerts { width: 200px; } -source-code-component { +tf-debugger-v2-source-files { display: inline-block; height: 100%; + vertical-align: top; width: 70%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html index 93b80f47dd..08f1a79c0a 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html @@ -26,11 +26,7 @@
- - +
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts index 4eef6f6392..961d47caeb 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ts @@ -30,7 +30,4 @@ export class DebuggerComponent { @Input() activeRunId: string | null = null; - - @Input() - focusedSourceFileContent: SourceFileContent | null = null; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts index ba26e6e39e..83aa477c8b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container.ts @@ -17,11 +17,7 @@ import {createSelector, select, Store} from '@ngrx/store'; import {State} from './store/debugger_types'; import {debuggerLoaded} from './actions'; -import { - getActiveRunId, - getDebuggerRunListing, - getFocusedSourceFileContent, -} from './store'; +import {getActiveRunId, getDebuggerRunListing} from './store'; /** @typehack */ import * as _typeHackRxjs from 'rxjs'; @@ -32,7 +28,6 @@ import { [runs]="runs$ | async" [runIds]="runsIds$ | async" [activeRunId]="activeRunId$ | async" - [focusedSourceFileContent]="focusedSourceFileContent$ | async" > `, }) @@ -50,10 +45,6 @@ export class DebuggerContainer implements OnInit { readonly activeRunId$ = this.store.pipe(select(getActiveRunId)); - readonly focusedSourceFileContent$ = this.store.pipe( - select(getFocusedSourceFileContent) - ); - constructor(private readonly store: Store) {} ngOnInit(): void { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index 558c52f4df..91d48996f9 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -50,6 +50,7 @@ import {ExecutionDataContainer} from './views/execution_data/execution_data_cont import {ExecutionDataModule} from './views/execution_data/execution_data_module'; import {InactiveModule} from './views/inactive/inactive_module'; import {TimelineContainer} from './views/timeline/timeline_container'; +import {SourceCodeModule} from './views/source_code/source_code_module'; import {StackTraceContainer} from './views/stack_trace/stack_trace_container'; import {StackTraceModule} from './views/stack_trace/stack_trace_module'; import {TimelineModule} from './views/timeline/timeline_module'; @@ -68,6 +69,7 @@ describe('Debugger Container', () => { CommonModule, ExecutionDataModule, InactiveModule, + SourceCodeModule, StackTraceModule, TimelineModule, ], diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts index 0ca8137e59..424e02067c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts @@ -26,7 +26,8 @@ import {reducers} from './store/debugger_reducers'; import {DEBUGGER_FEATURE_KEY} from './store/debugger_types'; import {AlertsModule} from './views/alerts/alerts_module'; import {InactiveModule} from './views/inactive/inactive_module'; -import {SourceCodeModule} from './views/source_code/source_code_module'; +import {SourceCodeModule} from './views/source_code/source_code_module'; // TOOD(cais): Clean up. +import {SourceFilesModule} from './views/source_files/source_files_module'; // TOOD(cais): Clean up. import {StackTraceModule} from './views/stack_trace/stack_trace_module'; import {TimelineModule} from './views/timeline/timeline_module'; import {PluginRegistryModule} from '../../../webapp/plugins/plugin_registry_module'; @@ -38,6 +39,7 @@ import {PluginRegistryModule} from '../../../webapp/plugins/plugin_registry_modu CommonModule, InactiveModule, SourceCodeModule, + SourceFilesModule, StackTraceModule, Tfdbg2ServerDataSourceModule, TimelineModule, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD index e0cfc18e41..dfddfc6487 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD @@ -42,6 +42,7 @@ tf_ts_library( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", "//tensorboard/webapp/angular:expect_angular_core_testing", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts index 7cc05fd1bd..6bb8f0c744 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts @@ -35,6 +35,7 @@ import {AlertsContainer} from './alerts_container'; import {AlertsModule} from './alerts_module'; import {ExecutionDataModule} from '../execution_data/execution_data_module'; import {InactiveModule} from '../inactive/inactive_module'; +import {SourceCodeModule} from '../source_code/source_code_module'; import {StackTraceModule} from '../stack_trace/stack_trace_module'; import {TimelineModule} from '../timeline/timeline_module'; @@ -52,6 +53,7 @@ describe('Alerts Container', () => { CommonModule, ExecutionDataModule, InactiveModule, + SourceCodeModule, StackTraceModule, TimelineModule, ], diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD index c7fa2ea840..ba13abb6df 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD @@ -29,7 +29,6 @@ ng_module( ], ) - tf_ts_library( name = "load_monaco", srcs = [ diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css index e69de29bb2..c2a438ad19 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css @@ -0,0 +1,9 @@ +/* :host { + height: 600px; + width: 324px; +} */ + +.code-viewer-container { + height: 324px; + width: 640px; +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html index 6d2afbb394..3bc79aa025 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html @@ -15,6 +15,6 @@ limitations under the License. --> -
- Monaco Goes Here -
+ +
+ diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index 1ec7fb3499..e9c169e964 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -12,7 +12,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -import {Component, Input, OnInit} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + ElementRef, + Input, + OnInit, + SimpleChanges, + ViewChild, +} from '@angular/core'; import {loadMonaco, WindowWithRequireAndMonaco} from '../source_code/load_monaco_shim'; @@ -22,6 +30,7 @@ const windowWithRequireAndMonaco: WindowWithRequireAndMonaco = window; selector: 'source-code-component', templateUrl: './source_code_component.ng.html', styleUrls: ['./source_code_component.css'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class SourceCodeComponent implements OnInit { @Input() @@ -30,11 +39,35 @@ export class SourceCodeComponent implements OnInit { // @Input() // focusedLineno: number | null = null; + @ViewChild('codeViewerContainer', {static: true, read: ElementRef}) + private readonly codeViewerContainer!: ElementRef; + + private editor: any = null; + async ngOnInit(): Promise { - console.log('SourceCodeComponent.ngOnInit(): lines=', this.lines); // DEBUG - if (windowWithRequireAndMonaco.monaco === undefined) { + // if (windowWithRequireAndMonaco.monaco === undefined) { + // await loadMonaco(); + // console.log('Done loading monaco: lines=', this.lines); + // } + } + + async ngOnChanges(changes: SimpleChanges): Promise { + console.log('SourceCodeComponent.ngOnChanges():', changes); // DEBUG + if (changes['lines'] && this.lines !== null) { await loadMonaco(); - console.log('Done loading monaco:', windowWithRequireAndMonaco.monaco); + const monaco = windowWithRequireAndMonaco.monaco; + if (this.editor === null) { + this.editor = monaco.editor.create(this.codeViewerContainer.nativeElement, { + value: this.lines.join("\n"), + language: 'python', + // model: monaco.editor.createModel(value, 'python'), + minimap: { + enabled: true, + }, + }); + console.log('element:', this.codeViewerContainer.nativeElement); + console.log('style.height:', this.codeViewerContainer.nativeElement.style.height); + } } } } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD new file mode 100644 index 0000000000..4ac43e82f4 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD @@ -0,0 +1,27 @@ +package(default_visibility = ["//tensorboard:internal"]) + +load("@npm_angular_bazel//:index.bzl", "ng_module") + +licenses(["notice"]) # Apache 2.0 + +ng_module( + name = "source_files", + srcs = [ + "source_files_component.ts", + "source_files_container.ts", + "source_files_module.ts", + ], + assets = [ + "source_files_component.css", + "source_files_component.ng.html", + ], + deps = [ + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code", + "@npm//@angular/common", + "@npm//@angular/core", + "@npm//@ngrx/store", + "@npm//rxjs", + ], +) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css new file mode 100644 index 0000000000..151f9f0113 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -0,0 +1,10 @@ +.header-section { + height: 36px; + width: 100%; +} + +source-code-component { + /* display: flex; */ + height: 324px; + width: 100%; +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html new file mode 100644 index 0000000000..7bab756ef9 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -0,0 +1,27 @@ + + +
+
+ Source Files Container +
+ + +
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts new file mode 100644 index 0000000000..2652258787 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts @@ -0,0 +1,27 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +import {Component, Input} from '@angular/core'; + +import {SourceFileContent} from '../../store/debugger_types'; + +@Component({ + selector: 'source-files-component', + templateUrl: './source_files_component.ng.html', + styleUrls: ['./source_files_component.css'], +}) +export class SourceFilesComponent { + @Input() + focusedSourceFileContent: SourceFileContent | null = null; +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts new file mode 100644 index 0000000000..30e0eba094 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts @@ -0,0 +1,37 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +import {Component} from '@angular/core'; +import {select, Store} from '@ngrx/store'; + +import {getFocusedSourceFileContent} from '../../store'; +import {State} from '../../store/debugger_types'; + +/** @typehack */ import * as _typeHackRxjs from 'rxjs'; + +@Component({ + selector: 'tf-debugger-v2-source-files', + template: ` + + `, +}) +export class SourceFilesContainer { + constructor(private readonly store: Store) {} + + readonly focusedSourceFileContent$ = this.store.pipe( + select(getFocusedSourceFileContent) + ); +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts new file mode 100644 index 0000000000..83232dd502 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts @@ -0,0 +1,31 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; + +import {SourceCodeModule} from '../source_code/source_code_module'; +import {SourceFilesComponent} from './source_files_component'; +import {SourceFilesContainer} from './source_files_container'; + +@NgModule({ + declarations: [SourceFilesComponent, SourceFilesContainer], + imports: [ + CommonModule, + SourceCodeModule, + ], + exports: [SourceFilesContainer], +}) +export class SourceFilesModule {} From 77500ccb8de2c7e2a9675b592d7d8aabb102b1bb Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 24 Mar 2020 16:42:14 -0400 Subject: [PATCH 03/21] Improve styling; add file_path display --- .../tf_debugger_v2_plugin/store/debugger_selectors.ts | 8 ++++++++ .../views/source_code/source_code_component.css | 7 +------ .../views/source_code/source_code_component.ts | 6 ++++-- .../views/source_files/source_files_component.css | 2 -- .../views/source_files/source_files_component.ng.html | 7 ++++++- .../views/source_files/source_files_component.ts | 5 ++++- .../views/source_files/source_files_container.ts | 7 ++++++- 7 files changed, 29 insertions(+), 13 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts index 6e19939549..182d66b9b8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts @@ -28,6 +28,7 @@ import { LoadState, SourceFileContent, SourceFileSpec, + SourceLineSpec, StackFrame, StackFramesById, State, @@ -331,3 +332,10 @@ export const getFocusedSourceFileContent = createSelector( return state.sourceCode.fileContents[fileIndex] || null; } ); + +export const getFocusedSourceLineSpec = createSelector( + selectDebuggerState, + (state: DebuggerState): SourceLineSpec | null => { + return state.sourceCode.focusLineSpec; + } +); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css index c2a438ad19..9303742d42 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css @@ -1,9 +1,4 @@ -/* :host { - height: 600px; - width: 324px; -} */ - .code-viewer-container { height: 324px; - width: 640px; + width: 100%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index e9c169e964..ac27870f79 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -26,6 +26,8 @@ import {loadMonaco, WindowWithRequireAndMonaco} from '../source_code/load_monaco const windowWithRequireAndMonaco: WindowWithRequireAndMonaco = window; +const DEFAULT_CODE_FONT_SIZE = 10; + @Component({ selector: 'source-code-component', templateUrl: './source_code_component.ng.html', @@ -60,13 +62,13 @@ export class SourceCodeComponent implements OnInit { this.editor = monaco.editor.create(this.codeViewerContainer.nativeElement, { value: this.lines.join("\n"), language: 'python', - // model: monaco.editor.createModel(value, 'python'), + readOnly: true, + fontSize: DEFAULT_CODE_FONT_SIZE, minimap: { enabled: true, }, }); console.log('element:', this.codeViewerContainer.nativeElement); - console.log('style.height:', this.codeViewerContainer.nativeElement.style.height); } } } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index 151f9f0113..ab0af0909a 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -4,7 +4,5 @@ } source-code-component { - /* display: flex; */ - height: 324px; width: 100%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index 7bab756ef9..25d582547a 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -17,7 +17,12 @@
- Source Files Container + Source Code + + {{ focusedSourceLineSpec.file_path }} +
`, }) @@ -34,4 +35,8 @@ export class SourceFilesContainer { readonly focusedSourceFileContent$ = this.store.pipe( select(getFocusedSourceFileContent) ); + + readonly focusedSourceLineSpec$ = this.store.pipe( + select(getFocusedSourceLineSpec) + ); } From e13ff3985013d3aa1d3066e3df5c48fd549028f6 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 24 Mar 2020 17:30:07 -0400 Subject: [PATCH 04/21] Line scrolling-to and highlighting is basically working --- .../source_code/source_code_component.css | 9 +++++ .../source_code/source_code_component.ts | 38 ++++++++++++++++--- .../source_files_component.ng.html | 3 +- .../stack_trace/stack_trace_component.css | 2 +- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css index 9303742d42..879ed58ba0 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css @@ -2,3 +2,12 @@ height: 324px; width: 100%; } + +:host ::ng-deep .highlight-gutter { + background: rgba(255, 111, 0, 0.7); + width: 5px; +} + +:host ::ng-deep .highlight-line { + background: rgba(255, 111, 0, 0.3); +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index ac27870f79..e2a839696a 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -38,14 +38,16 @@ export class SourceCodeComponent implements OnInit { @Input() lines: string[] | null = null; // TODO(cais): Add spinner for `null`. - // @Input() - // focusedLineno: number | null = null; + @Input() + focusedLineno: number | null = null; @ViewChild('codeViewerContainer', {static: true, read: ElementRef}) private readonly codeViewerContainer!: ElementRef; private editor: any = null; + private decorations: string[] = []; + async ngOnInit(): Promise { // if (windowWithRequireAndMonaco.monaco === undefined) { // await loadMonaco(); @@ -55,12 +57,13 @@ export class SourceCodeComponent implements OnInit { async ngOnChanges(changes: SimpleChanges): Promise { console.log('SourceCodeComponent.ngOnChanges():', changes); // DEBUG - if (changes['lines'] && this.lines !== null) { - await loadMonaco(); - const monaco = windowWithRequireAndMonaco.monaco; + await loadMonaco(); + const monaco = windowWithRequireAndMonaco.monaco; + if (changes.lines && this.lines !== null) { + const value = this.lines.join("\n"); if (this.editor === null) { this.editor = monaco.editor.create(this.codeViewerContainer.nativeElement, { - value: this.lines.join("\n"), + value, language: 'python', readOnly: true, fontSize: DEFAULT_CODE_FONT_SIZE, @@ -69,7 +72,30 @@ export class SourceCodeComponent implements OnInit { }, }); console.log('element:', this.codeViewerContainer.nativeElement); + } else { + this.editor.setValue(value); } } + if (changes.focusedLineno && this.lines && this.focusedLineno) { + console.log('focusedLineno = ', this.focusedLineno); // DEBUG + this.editor.revealLineInCenter( + this.focusedLineno, monaco.editor.ScrollType.Smooth); + const lineLength = this.lines[this.focusedLineno - 1].length; + this.decorations = this.editor.deltaDecorations(this.decorations, [ + { + range: new monaco.Range(this.focusedLineno, 1, this.focusedLineno, 1), + options: { + isWholeLine: true, + linesDecorationsClassName: 'highlight-gutter', + } + }, + { + range: new monaco.Range(this.focusedLineno, 1, this.focusedLineno, lineLength + 1), + options: { + inlineClassName: 'highlight-line', + } + }, + ]); + } } } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index 25d582547a..acd2124f1e 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -25,8 +25,9 @@
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css index 272bcb6667..2be6ba0d92 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css @@ -14,7 +14,7 @@ limitations under the License. ==============================================================================*/ .stack-frame-array { - height: 340px; + height: 360px; overflow-x: auto; overflow-y: auto; } From 6bcb5a62e7a417804d11c74db6f31899a9fd6819 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 24 Mar 2020 23:39:18 -0400 Subject: [PATCH 05/21] Working on stying the source files header --- .../debugger_component.css | 5 ++-- .../effects/debugger_effects.ts | 3 +- .../source_code/source_code_component.css | 4 +-- .../source_files/source_files_component.css | 29 ++++++++++++++++++- .../source_files_component.ng.html | 10 +++++-- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css index b73186f1b8..92ccb10f2b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css @@ -14,6 +14,7 @@ limitations under the License. ==============================================================================*/ .bottom-section { + border-top: 1px solid rgba(0, 0, 0, 0.12); height: 360px; width: 100%; } @@ -32,6 +33,7 @@ tf-debugger-v2-alerts { tf-debugger-v2-source-files { display: inline-block; height: 100%; + /* padding-right: 3px; */ vertical-align: top; width: 70%; } @@ -39,9 +41,6 @@ tf-debugger-v2-source-files { tf-debugger-v2-stack-trace { display: inline-block; width: 30%; - /* TODO(cais): Once code-editor component is added to the left, - replace the `float` with a linear layout. */ - /* float: right; */ } tf-debugger-v2-timeline { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index 2ef03bbc39..96732e4c2b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -675,7 +675,8 @@ export class DebuggerEffects { return ( runId !== null && fileContent !== null && - fileContent.loadState !== DataLoadState.LOADING + // TODO(cais): Cover with unit test. + fileContent.loadState === DataLoadState.NOT_LOADED ); }), tap(({lineSpec}) => diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css index 879ed58ba0..ff81801e66 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css @@ -1,11 +1,11 @@ .code-viewer-container { - height: 324px; + height: 336px; width: 100%; } :host ::ng-deep .highlight-gutter { background: rgba(255, 111, 0, 0.7); - width: 5px; + width: 5px !important; } :host ::ng-deep .highlight-line { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index ab0af0909a..c7b06678d8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -1,8 +1,35 @@ +:host { + font-family: 'Roboto', Arial, Helvetica, sans-serif; +} + .header-section { - height: 36px; + border-bottom: 1px solid rgba(0, 0, 0, 0.12); + font-size: 12px; + font-weight: 500; + height: 28px; + vertical-align: middle; width: 100%; } +.file-label { + display: inline-block; + direction: rtl; + font-size: 11px; + font-weight: 400; + height: 100%; + overflow: hidden; + text-align: left; + text-overflow: ellipsis; + white-space: nowrap; + width: 240px; + padding: 0 12px; +} + +.title-tag { + display: inline-block; + height: 100%; +} + source-code-component { width: 100%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index acd2124f1e..11e51d7e4a 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -17,13 +17,17 @@
- Source Code - + Source Code +
+
{{ focusedSourceLineSpec.file_path }} - +
+ Date: Wed, 25 Mar 2020 13:15:23 -0400 Subject: [PATCH 06/21] Fix styling --- .../debugger_component.css | 1 + .../tf_debugger_v2_plugin/debugger_module.ts | 4 +- .../source_code/source_code_component.ng.html | 2 - .../source_code/source_code_component.ts | 60 ++++++++++--------- .../source_files/source_files_component.css | 19 +++--- .../source_files_component.ng.html | 5 +- .../source_files/source_files_container.ts | 5 +- .../views/source_files/source_files_module.ts | 5 +- .../stack_trace/stack_trace_component.css | 3 + .../stack_trace/stack_trace_component.ts | 6 +- .../stack_trace/stack_trace_container.ts | 10 ++-- .../views/stack_trace/stack_trace_module.ts | 5 +- 12 files changed, 59 insertions(+), 66 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css index 92ccb10f2b..42d01c80fa 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css @@ -16,6 +16,7 @@ limitations under the License. .bottom-section { border-top: 1px solid rgba(0, 0, 0, 0.12); height: 360px; + padding-top: 6px; width: 100%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts index 424e02067c..1bed374081 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts @@ -26,8 +26,8 @@ import {reducers} from './store/debugger_reducers'; import {DEBUGGER_FEATURE_KEY} from './store/debugger_types'; import {AlertsModule} from './views/alerts/alerts_module'; import {InactiveModule} from './views/inactive/inactive_module'; -import {SourceCodeModule} from './views/source_code/source_code_module'; // TOOD(cais): Clean up. -import {SourceFilesModule} from './views/source_files/source_files_module'; // TOOD(cais): Clean up. +import {SourceCodeModule} from './views/source_code/source_code_module'; // TOOD(cais): Clean up. +import {SourceFilesModule} from './views/source_files/source_files_module'; // TOOD(cais): Clean up. import {StackTraceModule} from './views/stack_trace/stack_trace_module'; import {TimelineModule} from './views/timeline/timeline_module'; import {PluginRegistryModule} from '../../../webapp/plugins/plugin_registry_module'; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html index 3bc79aa025..ad919b4e4b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ng.html @@ -15,6 +15,4 @@ limitations under the License. --> -
- diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index e2a839696a..8ddb74c924 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -17,12 +17,14 @@ import { Component, ElementRef, Input, - OnInit, SimpleChanges, ViewChild, } from '@angular/core'; -import {loadMonaco, WindowWithRequireAndMonaco} from '../source_code/load_monaco_shim'; +import { + loadMonaco, + WindowWithRequireAndMonaco, +} from '../source_code/load_monaco_shim'; const windowWithRequireAndMonaco: WindowWithRequireAndMonaco = window; @@ -32,11 +34,11 @@ const DEFAULT_CODE_FONT_SIZE = 10; selector: 'source-code-component', templateUrl: './source_code_component.ng.html', styleUrls: ['./source_code_component.css'], - changeDetection: ChangeDetectionStrategy.OnPush + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SourceCodeComponent implements OnInit { +export class SourceCodeComponent { @Input() - lines: string[] | null = null; // TODO(cais): Add spinner for `null`. + lines: string[] | null = null; // TODO(cais): Add spinner for `null`. @Input() focusedLineno: number | null = null; @@ -48,38 +50,33 @@ export class SourceCodeComponent implements OnInit { private decorations: string[] = []; - async ngOnInit(): Promise { - // if (windowWithRequireAndMonaco.monaco === undefined) { - // await loadMonaco(); - // console.log('Done loading monaco: lines=', this.lines); - // } - } - async ngOnChanges(changes: SimpleChanges): Promise { - console.log('SourceCodeComponent.ngOnChanges():', changes); // DEBUG await loadMonaco(); const monaco = windowWithRequireAndMonaco.monaco; if (changes.lines && this.lines !== null) { - const value = this.lines.join("\n"); + const value = this.lines.join('\n'); if (this.editor === null) { - this.editor = monaco.editor.create(this.codeViewerContainer.nativeElement, { - value, - language: 'python', - readOnly: true, - fontSize: DEFAULT_CODE_FONT_SIZE, - minimap: { - enabled: true, - }, - }); - console.log('element:', this.codeViewerContainer.nativeElement); + this.editor = monaco.editor.create( + this.codeViewerContainer.nativeElement, + { + value, + language: 'python', + readOnly: true, + fontSize: DEFAULT_CODE_FONT_SIZE, + minimap: { + enabled: true, + }, + } + ); } else { this.editor.setValue(value); } } if (changes.focusedLineno && this.lines && this.focusedLineno) { - console.log('focusedLineno = ', this.focusedLineno); // DEBUG this.editor.revealLineInCenter( - this.focusedLineno, monaco.editor.ScrollType.Smooth); + this.focusedLineno, + monaco.editor.ScrollType.Smooth + ); const lineLength = this.lines[this.focusedLineno - 1].length; this.decorations = this.editor.deltaDecorations(this.decorations, [ { @@ -87,13 +84,18 @@ export class SourceCodeComponent implements OnInit { options: { isWholeLine: true, linesDecorationsClassName: 'highlight-gutter', - } + }, }, { - range: new monaco.Range(this.focusedLineno, 1, this.focusedLineno, lineLength + 1), + range: new monaco.Range( + this.focusedLineno, + 1, + this.focusedLineno, + lineLength + 1 + ), options: { inlineClassName: 'highlight-line', - } + }, }, ]); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index c7b06678d8..e394eb03d6 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -1,33 +1,30 @@ :host { - font-family: 'Roboto', Arial, Helvetica, sans-serif; + font-family: 'Roboto Mono', monospace; + font-size: 10px; } .header-section { border-bottom: 1px solid rgba(0, 0, 0, 0.12); - font-size: 12px; - font-weight: 500; height: 28px; vertical-align: middle; + white-space: nowrap; width: 100%; } .file-label { display: inline-block; - direction: rtl; - font-size: 11px; - font-weight: 400; + font-weight: normal; height: 100%; - overflow: hidden; text-align: left; - text-overflow: ellipsis; - white-space: nowrap; - width: 240px; - padding: 0 12px; + white-space: normal; + padding: 0 20px; } .title-tag { display: inline-block; + font-weight: bold; height: 100%; + vertical-align: top; } source-code-component { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index 11e51d7e4a..02a4c66432 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -20,10 +20,7 @@
Source Code
-
+
{{ focusedSourceLineSpec.file_path }}
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts index 0112d29e90..3ff9351226 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container.ts @@ -15,7 +15,10 @@ limitations under the License. import {Component} from '@angular/core'; import {select, Store} from '@ngrx/store'; -import {getFocusedSourceFileContent, getFocusedSourceLineSpec} from '../../store'; +import { + getFocusedSourceFileContent, + getFocusedSourceLineSpec, +} from '../../store'; import {State} from '../../store/debugger_types'; /** @typehack */ import * as _typeHackRxjs from 'rxjs'; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts index 83232dd502..d1dbd8d965 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_module.ts @@ -22,10 +22,7 @@ import {SourceFilesContainer} from './source_files_container'; @NgModule({ declarations: [SourceFilesComponent, SourceFilesContainer], - imports: [ - CommonModule, - SourceCodeModule, - ], + imports: [CommonModule, SourceCodeModule], exports: [SourceFilesContainer], }) export class SourceFilesModule {} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css index 2be6ba0d92..e4214ba1b6 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css @@ -51,10 +51,13 @@ limitations under the License. } .stack-trace-container { + border-left: 1px solid rgba(0, 0, 0, 0.12); font-size: 10px; font-family: 'Roboto Mono', monospace; height: 360px; + margin-left: 8px; max-height: 360px; + padding-left: 8px; width: 400px; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts index ad099200a5..30e5e203df 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ts @@ -33,8 +33,8 @@ export class StackTraceComponent { @Output() onSourceLineClicked = new EventEmitter<{ - host_name: string, - file_path: string, - lineno: number, + host_name: string; + file_path: string; + lineno: number; }>(); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts index d03ea2b374..07b432c8dc 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_container.ts @@ -23,7 +23,6 @@ import {StackFrameForDisplay} from './stack_trace_component'; /** @typehack */ import * as _typeHackRxjs from 'rxjs'; - @Component({ selector: 'tf-debugger-v2-stack-trace', template: ` @@ -64,12 +63,11 @@ export class StackTraceContainer { constructor(private readonly store: Store) {} onSourceLineClicked(args: { - host_name: string, - file_path: string, - lineno: number, + host_name: string; + file_path: string; + lineno: number; }) { - console.log( - 'StackTraceContainer.onSourceLineClicked: args:', args); // DEBUG + console.log('StackTraceContainer.onSourceLineClicked: args:', args); // DEBUG this.store.dispatch(sourceLineFocused({sourceLineSpec: args})); } } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts index 16034add18..5abd9b304c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_module.ts @@ -22,10 +22,7 @@ import {StackTraceContainer} from './stack_trace_container'; @NgModule({ declarations: [StackTraceComponent, StackTraceContainer], - imports: [ - CommonModule, - SourceCodeModule, - ], + imports: [CommonModule, SourceCodeModule], exports: [StackTraceContainer], }) export class StackTraceModule {} From c3ffc437e590b64f4171b4e462006a5ef3226eb7 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 25 Mar 2020 13:28:29 -0400 Subject: [PATCH 07/21] Add "no-file-selected" display --- .../views/source_files/source_files_component.css | 1 + .../views/source_files/source_files_component.ng.html | 9 ++++++++- .../views/stack_trace/stack_trace_container.ts | 1 - 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index e394eb03d6..b58e20c357 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -6,6 +6,7 @@ .header-section { border-bottom: 1px solid rgba(0, 0, 0, 0.12); height: 28px; + padding-bottom: 6px; vertical-align: middle; white-space: nowrap; width: 100%; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index 02a4c66432..15b8f2dfa0 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -20,9 +20,16 @@
Source Code
-
+
{{ focusedSourceLineSpec.file_path }}
+ + + (No file selected) +
Date: Wed, 25 Mar 2020 13:41:33 -0400 Subject: [PATCH 08/21] Clean up some ng module dependencies --- tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD | 2 +- .../tf_debugger_v2_plugin/debugger_container_test.ts | 4 ++-- .../debugger_v2/tf_debugger_v2_plugin/debugger_module.ts | 4 +--- .../debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD | 2 +- .../views/alerts/alerts_container_test.ts | 4 ++-- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD index b8dc693cbc..9eb8e27fce 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD @@ -55,7 +55,7 @@ tf_ts_library( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", - "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", "//tensorboard/webapp/angular:expect_angular_core_testing", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index 91d48996f9..e6e66a51fe 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -50,7 +50,7 @@ import {ExecutionDataContainer} from './views/execution_data/execution_data_cont import {ExecutionDataModule} from './views/execution_data/execution_data_module'; import {InactiveModule} from './views/inactive/inactive_module'; import {TimelineContainer} from './views/timeline/timeline_container'; -import {SourceCodeModule} from './views/source_code/source_code_module'; +import {SourceFilesModule} from './views/source_files/source_files_module'; import {StackTraceContainer} from './views/stack_trace/stack_trace_container'; import {StackTraceModule} from './views/stack_trace/stack_trace_module'; import {TimelineModule} from './views/timeline/timeline_module'; @@ -69,7 +69,7 @@ describe('Debugger Container', () => { CommonModule, ExecutionDataModule, InactiveModule, - SourceCodeModule, + SourceFilesModule, StackTraceModule, TimelineModule, ], diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts index 1bed374081..fa7881984c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_module.ts @@ -26,8 +26,7 @@ import {reducers} from './store/debugger_reducers'; import {DEBUGGER_FEATURE_KEY} from './store/debugger_types'; import {AlertsModule} from './views/alerts/alerts_module'; import {InactiveModule} from './views/inactive/inactive_module'; -import {SourceCodeModule} from './views/source_code/source_code_module'; // TOOD(cais): Clean up. -import {SourceFilesModule} from './views/source_files/source_files_module'; // TOOD(cais): Clean up. +import {SourceFilesModule} from './views/source_files/source_files_module'; import {StackTraceModule} from './views/stack_trace/stack_trace_module'; import {TimelineModule} from './views/timeline/timeline_module'; import {PluginRegistryModule} from '../../../webapp/plugins/plugin_registry_module'; @@ -38,7 +37,6 @@ import {PluginRegistryModule} from '../../../webapp/plugins/plugin_registry_modu AlertsModule, CommonModule, InactiveModule, - SourceCodeModule, SourceFilesModule, StackTraceModule, Tfdbg2ServerDataSourceModule, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD index dfddfc6487..c984eebaa7 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/BUILD @@ -42,7 +42,7 @@ tf_ts_library( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", - "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", "//tensorboard/webapp/angular:expect_angular_core_testing", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts index 6bb8f0c744..80c473241c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts/alerts_container_test.ts @@ -35,7 +35,7 @@ import {AlertsContainer} from './alerts_container'; import {AlertsModule} from './alerts_module'; import {ExecutionDataModule} from '../execution_data/execution_data_module'; import {InactiveModule} from '../inactive/inactive_module'; -import {SourceCodeModule} from '../source_code/source_code_module'; +import {SourceFilesModule} from '../source_files/source_files_module'; import {StackTraceModule} from '../stack_trace/stack_trace_module'; import {TimelineModule} from '../timeline/timeline_module'; @@ -53,7 +53,7 @@ describe('Alerts Container', () => { CommonModule, ExecutionDataModule, InactiveModule, - SourceCodeModule, + SourceFilesModule, StackTraceModule, TimelineModule, ], From 33b07f851054137c777363fe5ebf458aed886513 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 25 Mar 2020 14:06:26 -0400 Subject: [PATCH 09/21] Add unit test for dispatching sourceLineFocused action --- .../debugger_container_test.ts | 63 ++++++++++++++++++- .../views/source_code/BUILD | 5 -- .../source_files_component.ng.html | 4 +- .../stack_trace/stack_trace_component.ng.html | 8 ++- 4 files changed, 69 insertions(+), 11 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index e6e66a51fe..0310fb51d7 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -27,6 +27,7 @@ import { executionScrollLeft, executionScrollRight, executionScrollToIndex, + sourceLineFocused, } from './actions'; import {DebuggerComponent} from './debugger_component'; import {DebuggerContainer} from './debugger_container'; @@ -960,13 +961,13 @@ describe('Debugger Container', () => { ); expect(linenoElements.length).toEqual(3); expect(linenoElements[0].nativeElement.innerText).toEqual( - `Line ${stackFrame0[2]}:` + `Line ${stackFrame0[2]}` ); expect(linenoElements[1].nativeElement.innerText).toEqual( - `Line ${stackFrame1[2]}:` + `Line ${stackFrame1[2]}` ); expect(linenoElements[2].nativeElement.innerText).toEqual( - `Line ${stackFrame2[2]}:` + `Line ${stackFrame2[2]}` ); const functionElements = fixture.debugElement.queryAll( @@ -1024,5 +1025,61 @@ describe('Debugger Container', () => { ); expect(stackFrameContainers.length).toEqual(0); }); + + it('Emits sourceLineFocused when line number is clickedd', () => { + const fixture = TestBed.createComponent(StackTraceContainer); + fixture.detectChanges(); + + const stackFrame0 = createTestStackFrame(); + const stackFrame1 = createTestStackFrame(); + const stackFrame2 = createTestStackFrame(); + store.setState( + createState( + createDebuggerState({ + executions: { + numExecutionsLoaded: { + state: DataLoadState.LOADED, + lastLoadedTimeInMs: 111, + }, + executionDigestsLoaded: { + state: DataLoadState.LOADED, + lastLoadedTimeInMs: 222, + pageLoadedSizes: {0: 100}, + numExecutions: 1000, + }, + executionDigests: {}, + pageSize: 100, + displayCount: 50, + scrollBeginIndex: 90, + focusIndex: 98, + executionData: { + 98: createTestExecutionData({ + stack_frame_ids: ['a0', 'a1', 'a2'], + }), + }, + }, + stackFrames: { + a0: stackFrame0, + a1: stackFrame1, + a2: stackFrame2, + }, + }) + ) + ); + fixture.detectChanges(); + + const linenoElements = fixture.debugElement.queryAll( + By.css('.stack-frame-lineno') + ); + linenoElements[1].nativeElement.click(); + fixture.detectChanges(); + expect(dispatchSpy).toHaveBeenCalledWith(sourceLineFocused({ + sourceLineSpec: { + host_name: stackFrame1[0], + file_path: stackFrame1[1], + lineno: stackFrame1[2], + } + })); + }); }); }); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD index ba13abb6df..0d57cb420c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD @@ -17,11 +17,6 @@ ng_module( ], deps = [ ":load_monaco", - # TODO(cais): Clean up. - # "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:tf_types", - # "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", - "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", - "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", "@npm//@angular/common", "@npm//@angular/core", "@npm//@ngrx/store", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index 15b8f2dfa0..93010e3b07 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -33,7 +33,9 @@
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html index 0c8a194a7a..173928094f 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html @@ -46,9 +46,13 @@
- Line {{ stackFrameForDisplay.lineno }}: + Line {{ stackFrameForDisplay.lineno }}
{{ stackFrameForDisplay.function_name }} From d7ffa33680de330a9d12da453470049251856f20 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 25 Mar 2020 14:10:32 -0400 Subject: [PATCH 10/21] Back out some unwanted changes --- .../effects/debugger_effects.ts | 1 - tensorboard/webapp/BUILD | 1 - tensorboard/webapp/index.uninlined.html | 1 - yarn.lock | 149 ++++++++++++++++-- 4 files changed, 138 insertions(+), 14 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index 96732e4c2b..eae5fc3bb4 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -675,7 +675,6 @@ export class DebuggerEffects { return ( runId !== null && fileContent !== null && - // TODO(cais): Cover with unit test. fileContent.loadState === DataLoadState.NOT_LOADED ); }), diff --git a/tensorboard/webapp/BUILD b/tensorboard/webapp/BUILD index 9336ce2f35..0592cda9a7 100644 --- a/tensorboard/webapp/BUILD +++ b/tensorboard/webapp/BUILD @@ -111,7 +111,6 @@ tf_web_library( deps = [ ":tb_webapp", "//tensorboard/components:ng_polymer_lib_binary", - # TODO(cais): Add copybara rule. "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/monaco:requirejs", ], ) diff --git a/tensorboard/webapp/index.uninlined.html b/tensorboard/webapp/index.uninlined.html index 89f3f5c72e..50321bafb5 100644 --- a/tensorboard/webapp/index.uninlined.html +++ b/tensorboard/webapp/index.uninlined.html @@ -24,7 +24,6 @@ - diff --git a/yarn.lock b/yarn.lock index 0fbcf94316..d30f945922 100644 --- a/yarn.lock +++ b/yarn.lock @@ -493,6 +493,11 @@ JSONStream@^1.3.4: jsonparse "^1.2.0" through ">=2.2.7 <3" +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + accepts@~1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -617,11 +622,19 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.1.1: +aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + argparse@~1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1131,6 +1144,11 @@ connect@^3.6.0: parseurl "~1.3.3" utils-merge "1.0.1" +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -1261,6 +1279,11 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -1295,6 +1318,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1305,6 +1333,11 @@ dependency-graph@^0.7.2: resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.7.2.tgz#91db9de6eb72699209d88aea4c1fd5221cac1c49" integrity sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ== +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -1773,6 +1806,20 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + genfun@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" @@ -1895,6 +1942,11 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -2003,7 +2055,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -2060,7 +2112,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@1.3.5: +ini@1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -2870,6 +2922,15 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +needle@^2.2.1: + version "2.3.3" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.3.tgz#a041ad1d04a871b0ebb666f40baaf1fb47867117" + integrity sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -2905,6 +2966,30 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" +node-pre-gyp@*: + version "0.14.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" + integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4.4.2" + +nopt@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -2959,7 +3044,7 @@ npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: semver "^5.6.0" validate-npm-package-name "^3.0.0" -npm-packlist@^1.1.12: +npm-packlist@^1.1.12, npm-packlist@^1.1.6: version "1.4.8" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== @@ -3006,6 +3091,16 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + null-check@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" @@ -3021,6 +3116,11 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" @@ -3132,7 +3232,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.5: +osenv@^0.1.4, osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -3461,6 +3561,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + read-package-json@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" @@ -3499,7 +3609,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -3678,7 +3788,7 @@ rimraf@3.0.0: dependencies: glob "^7.1.3" -rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: +rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -3753,6 +3863,11 @@ saucelabs@^1.5.0: dependencies: https-proxy-agent "^2.2.1" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + selenium-webdriver@^4.0.0-alpha.1: version "4.0.0-alpha.7" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.7.tgz#e3879d8457fd7ad8e4424094b7dc0540d99e6797" @@ -3769,7 +3884,7 @@ semver-intersect@1.4.0: dependencies: semver "^5.0.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -3784,7 +3899,7 @@ semver@6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -set-blocking@^2.0.0: +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -4107,7 +4222,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -4194,6 +4309,11 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + supports-color@^3.1.2: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" @@ -4213,7 +4333,7 @@ symbol-observable@1.2.0: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== -tar@^4.4.8: +tar@^4.4.2, tar@^4.4.8: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -4565,6 +4685,13 @@ which@^1.2.1, which@^1.2.9, which@^1.3.0, which@^1.3.1: dependencies: isexe "^2.0.0" +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" From 7d3fcf6d7718c791a29430150b9f2d02d8a46973 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 25 Mar 2020 16:08:09 -0400 Subject: [PATCH 11/21] Add source_files_container_test.ts: Unit tests for source_file_container --- .../debugger_v2/tf_debugger_v2_plugin/BUILD | 1 + .../debugger_container_test.ts | 16 +- .../views/source_files/BUILD | 31 +++ .../source_files/source_files_component.css | 9 +- .../source_files_component.ng.html | 6 +- .../source_files_container_test.ts | 225 ++++++++++++++++++ 6 files changed, 278 insertions(+), 10 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD index 9eb8e27fce..8631e98b09 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD @@ -77,6 +77,7 @@ tf_ng_web_test_suite( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debugger_store_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts:alerts_container_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_test_lib", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files:source_files_container_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline:timeline_test", ], ) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index 0310fb51d7..1948925849 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -1073,13 +1073,15 @@ describe('Debugger Container', () => { ); linenoElements[1].nativeElement.click(); fixture.detectChanges(); - expect(dispatchSpy).toHaveBeenCalledWith(sourceLineFocused({ - sourceLineSpec: { - host_name: stackFrame1[0], - file_path: stackFrame1[1], - lineno: stackFrame1[2], - } - })); + expect(dispatchSpy).toHaveBeenCalledWith( + sourceLineFocused({ + sourceLineSpec: { + host_name: stackFrame1[0], + file_path: stackFrame1[1], + lineno: stackFrame1[2], + }, + }) + ); }); }); }); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD index 4ac43e82f4..ec0388b5ac 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD @@ -1,6 +1,7 @@ package(default_visibility = ["//tensorboard:internal"]) load("@npm_angular_bazel//:index.bzl", "ng_module") +load("//tensorboard/defs:defs.bzl", "tf_ts_library") licenses(["notice"]) # Apache 2.0 @@ -25,3 +26,33 @@ ng_module( "@npm//rxjs", ], ) + +tf_ts_library( + name = "source_files_container_test_lib", + testonly = True, + srcs = [ + "source_files_container_test.ts", + ], + tsconfig = "//:tsconfig-test", + deps = [ + ":source_files", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:debugger_v2", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:load_monaco", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", + "//tensorboard/webapp/angular:expect_angular_core_testing", + "//tensorboard/webapp/angular:expect_ngrx_store_testing", + "@npm//@angular/common", + "@npm//@angular/compiler", + "@npm//@angular/core", + "@npm//@angular/platform-browser", + "@npm//@ngrx/store", + "@npm//@types/jasmine", + ], +) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index b58e20c357..098aaf44ab 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -15,16 +15,21 @@ .file-label { display: inline-block; font-weight: normal; - height: 100%; - text-align: left; white-space: normal; padding: 0 20px; } +.no-file-selected { + display: inline-block; + color: #666; + padding: 0 20px; +} + .title-tag { display: inline-block; font-weight: bold; height: 100%; + padding-left: 6px; vertical-align: top; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index 93010e3b07..7ddff7fdba 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -20,6 +20,8 @@
Source Code
+ +
- (No file selected) +
+ (No file selected) +
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts new file mode 100644 index 0000000000..7c2d8fa1e1 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts @@ -0,0 +1,225 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +/** + * Unit tests for the the Source Files component and container. + */ +import {CommonModule} from '@angular/common'; +import {TestBed} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; + +import {Store} from '@ngrx/store'; +import {provideMockStore, MockStore} from '@ngrx/store/testing'; + +import {DebuggerComponent} from '../../debugger_component'; +import {DebuggerContainer} from '../../debugger_container'; +import {DataLoadState, State} from '../../store/debugger_types'; +import {createDebuggerState, createState} from '../../testing'; +import {AlertsModule} from '../alerts/alerts_module'; +import {ExecutionDataModule} from '../execution_data/execution_data_module'; +import {InactiveModule} from '../inactive/inactive_module'; +import * as loadMonacoShim from '../source_code/load_monaco_shim'; +import {StackTraceModule} from '../stack_trace/stack_trace_module'; +import { + getFocusedSourceFileContent, + getFocusedSourceLineSpec, +} from '../../store'; +import {TimelineModule} from '../timeline/timeline_module'; +import {SourceFilesContainer} from './source_files_container'; +import {SourceFilesModule} from './source_files_module'; + +/** @typehack */ import * as _typeHackStore from '@ngrx/store'; + +describe('Source Files Container', () => { + let store: MockStore; + let dispatchSpy: jasmine.Spy; + + class FakeRange { + constructor( + readonly startLineNumber: number, + readonly startColumn: number, + readonly endLineNumber: number, + readonly endColumn: number + ) {} + } + + let loadMonacoSpy: jasmine.Spy; + // TODO(cais): Explore better typing by depending on 3rd-party libraries. + let editorSpy: jasmine.SpyObj; + let monaco: any; + function setUpMonacoFakes() { + async function fakeLoadMonaco() { + monaco = { + editor: { + create: () => { + editorSpy = jasmine.createSpyObj('editorSpy', [ + 'deltaDecorations', + 'revealLineInCenter', + 'setValue', + ]); + return editorSpy; + }, + ScrollType: { + Immediate: 1, + Smooth: 0, + }, + }, + Range: FakeRange, + }; + loadMonacoShim.windowWithRequireAndMonaco.monaco = monaco; + } + loadMonacoSpy = spyOn(loadMonacoShim, 'loadMonaco').and.callFake( + fakeLoadMonaco + ); + } + + beforeEach(async () => { + setUpMonacoFakes(); + await TestBed.configureTestingModule({ + declarations: [DebuggerComponent, DebuggerContainer], + imports: [ + AlertsModule, + CommonModule, + ExecutionDataModule, + InactiveModule, + SourceFilesModule, + StackTraceModule, + TimelineModule, + ], + providers: [ + provideMockStore({ + initialState: createState(createDebuggerState()), + }), + DebuggerContainer, + ], + }).compileComponents(); + store = TestBed.get(Store); + dispatchSpy = spyOn(store, 'dispatch'); + }); + + it('renders no file selected when no source line is focused on', () => { + const fixture = TestBed.createComponent(SourceFilesContainer); + store.setState(createState(createDebuggerState())); + fixture.detectChanges(); + + const noFileSelectedElement = fixture.debugElement.query( + By.css('.no-file-selected') + ); + expect(noFileSelectedElement.nativeElement.innerText).toBe( + '(No file selected)' + ); + }); + + it('renders file path and editor when a file is focused on', async () => { + const fixture = TestBed.createComponent(SourceFilesContainer); + store.overrideSelector(getFocusedSourceFileContent, { + loadState: DataLoadState.LOADED, + lines: ['import tensorflow as tf', '', 'print("hello, world")'], + }); + store.overrideSelector(getFocusedSourceLineSpec, { + host_name: 'localhost', + file_path: '/home/user/main.py', + lineno: 2, + }); + fixture.detectChanges(); + await fixture.whenStable(); + + let fileLabelElement = fixture.debugElement.query(By.css('.file-label')); + expect(fileLabelElement.nativeElement.innerText).toBe('/home/user/main.py'); + expect(loadMonacoSpy).toHaveBeenCalledTimes(1); + expect(editorSpy.setValue).not.toHaveBeenCalled(); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(1); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 2, + monaco.editor.ScrollType.Smooth + ); + expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(1); + + // Check the behavior when a new file is focused on. + store.overrideSelector(getFocusedSourceFileContent, { + loadState: DataLoadState.LOADED, + lines: [ + 'model = tf.keras.Sequential', + 'model.add(tf.keras.layers.Dense(1))', + ], + }); + store.overrideSelector(getFocusedSourceLineSpec, { + host_name: 'localhost', + file_path: '/home/user/model.py', + lineno: 1, + }); + store.refreshState(); + fixture.detectChanges(); + await fixture.whenStable(); + + fileLabelElement = fixture.debugElement.query(By.css('.file-label')); + expect(fileLabelElement.nativeElement.innerText).toBe( + '/home/user/model.py' + ); + // Switching to a different file relies on setValue() to render the code + // of the new file. + expect(editorSpy.setValue).toHaveBeenCalledTimes(1); + expect(editorSpy.setValue).toHaveBeenCalledWith( + 'model = tf.keras.Sequential\nmodel.add(tf.keras.layers.Dense(1))' + ); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 1, + monaco.editor.ScrollType.Smooth + ); + expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(2); + }); + + it('switching to a different line in the same file', async () => { + const fixture = TestBed.createComponent(SourceFilesContainer); + store.overrideSelector(getFocusedSourceFileContent, { + loadState: DataLoadState.LOADED, + lines: ['import tensorflow as tf', '', 'print("hello, world")'], + }); + store.overrideSelector(getFocusedSourceLineSpec, { + host_name: 'localhost', + file_path: '/home/user/main.py', + lineno: 2, + }); + fixture.detectChanges(); + await fixture.whenStable(); + + // Check the behavior when a new file is focused on. + store.overrideSelector(getFocusedSourceLineSpec, { + host_name: 'localhost', + file_path: '/home/user/main.py', + lineno: 0, // Focusing on a different line of the same file. + }); + store.refreshState(); + fixture.detectChanges(); + await fixture.whenStable(); + + const fileLabelElement = fixture.debugElement.query(By.css('.file-label')); + expect(fileLabelElement.nativeElement.innerText).toBe('/home/user/main.py'); + // setValue() shouldn't have been called because there is no change in file + // content. + expect(editorSpy.setValue).toHaveBeenCalledTimes(0); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); + // This is the call for the old lineno. + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 2, + monaco.editor.ScrollType.Smooth + ); + // This is the call for the new lineno. + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 0, + monaco.editor.ScrollType.Smooth + ); + }); +}); From bbf5927d1987d16e78a9c3ffc77d2f73d1c29800 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 25 Mar 2020 16:26:47 -0400 Subject: [PATCH 12/21] Fix test; Add missing license headers to .css files --- .../debugger_container_test.ts | 2 +- .../views/source_code/source_code_component.css | 15 +++++++++++++++ .../source_files/source_files_container_test.ts | 10 ++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index 1948925849..eb9c49cdec 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -1026,7 +1026,7 @@ describe('Debugger Container', () => { expect(stackFrameContainers.length).toEqual(0); }); - it('Emits sourceLineFocused when line number is clickedd', () => { + it('Emits sourceLineFocused when line number is clicked', () => { const fixture = TestBed.createComponent(StackTraceContainer); fixture.detectChanges(); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css index ff81801e66..5724aaab7c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.css @@ -1,3 +1,18 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + .code-viewer-container { height: 336px; width: 100%; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts index 7c2d8fa1e1..b748414ae3 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts @@ -130,8 +130,9 @@ describe('Source Files Container', () => { store.overrideSelector(getFocusedSourceLineSpec, { host_name: 'localhost', file_path: '/home/user/main.py', - lineno: 2, + lineno: 3, }); + store.refreshState(); fixture.detectChanges(); await fixture.whenStable(); @@ -141,7 +142,7 @@ describe('Source Files Container', () => { expect(editorSpy.setValue).not.toHaveBeenCalled(); expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(1); expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( - 2, + 3, monaco.editor.ScrollType.Smooth ); expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(1); @@ -192,6 +193,7 @@ describe('Source Files Container', () => { file_path: '/home/user/main.py', lineno: 2, }); + store.refreshState(); fixture.detectChanges(); await fixture.whenStable(); @@ -199,7 +201,7 @@ describe('Source Files Container', () => { store.overrideSelector(getFocusedSourceLineSpec, { host_name: 'localhost', file_path: '/home/user/main.py', - lineno: 0, // Focusing on a different line of the same file. + lineno: 1, // Focusing on a different line of the same file. }); store.refreshState(); fixture.detectChanges(); @@ -218,7 +220,7 @@ describe('Source Files Container', () => { ); // This is the call for the new lineno. expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( - 0, + 1, monaco.editor.ScrollType.Smooth ); }); From 0e8421f5807d88fe1b0abf94938a5428ff89b026 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 25 Mar 2020 16:31:20 -0400 Subject: [PATCH 13/21] Add missing license header to .css file; Remove obsolete TODO item --- .../views/source_files/source_files_component.css | 15 +++++++++++++++ .../stack_trace/stack_trace_component.ng.html | 1 - 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index 098aaf44ab..32c45dabb6 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -1,3 +1,18 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + :host { font-family: 'Roboto Mono', monospace; font-size: 10px; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html index 173928094f..424c049e1c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.ng.html @@ -43,7 +43,6 @@ {{ stackFrameForDisplay.concise_file_path }}
-
{ await loadMonaco(); const monaco = windowWithRequireAndMonaco.monaco; - if (changes.lines && this.lines !== null) { - const value = this.lines.join('\n'); + let currentLines: string[] | null = this.lines; + if (changes.lines && changes.lines.currentValue !== null) { + currentLines = changes.lines.currentValue; + const value = changes.lines.currentValue.join('\n'); if (this.editor === null) { this.editor = monaco.editor.create( this.codeViewerContainer.nativeElement, { value, - language: 'python', + language: DEFAULT_CODE_LANGUAGE, readOnly: true, fontSize: DEFAULT_CODE_FONT_SIZE, minimap: { @@ -72,12 +90,19 @@ export class SourceCodeComponent { this.editor.setValue(value); } } - if (changes.focusedLineno && this.lines && this.focusedLineno) { + // TODO(cais): Use `this.lines` vs. `changes.focusedLineno.currentValue`. + if ( + changes.focusedLineno && + changes.focusedLineno.currentValue && + currentLines && + this.editor !== null + ) { this.editor.revealLineInCenter( this.focusedLineno, monaco.editor.ScrollType.Smooth ); - const lineLength = this.lines[this.focusedLineno - 1].length; + const lineLength = + currentLines[changes.focusedLineno.currentValue - 1].length; this.decorations = this.editor.deltaDecorations(this.decorations, [ { range: new monaco.Range(this.focusedLineno, 1, this.focusedLineno, 1), @@ -100,4 +125,12 @@ export class SourceCodeComponent { ]); } } + + @HostListener('window:resize', ['$event']) + onResize(event: Event) { + console.log('onResize'); // DEBUG + if (this.editor !== null) { + this.editor.layout(); + } + } } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts index aa494ce5bf..40a5e32c1b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts @@ -13,14 +13,12 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; import {SourceCodeComponent} from './source_code_component'; @NgModule({ declarations: [SourceCodeComponent], - imports: [CommonModule], exports: [SourceCodeComponent], }) export class SourceCodeModule {} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index 32c45dabb6..7493abf9c9 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -13,14 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -:host { - font-family: 'Roboto Mono', monospace; - font-size: 10px; -} - .header-section { border-bottom: 1px solid rgba(0, 0, 0, 0.12); - height: 28px; + height: 24px; padding-bottom: 6px; vertical-align: middle; white-space: nowrap; @@ -40,6 +35,14 @@ limitations under the License. padding: 0 20px; } +.source-files-container { + display: flex; + flex-direction: column; + font-family: 'Roboto Mono', monospace; + font-size: 10px; + height: 100%; +} + .title-tag { display: inline-block; font-weight: bold; @@ -49,5 +52,6 @@ limitations under the License. } source-code-component { + flex-grow: 1; width: 100%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts index 0e61e47d2c..919d0c62b4 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts @@ -103,12 +103,7 @@ describe('Source Files Container', () => { StackTraceModule, TimelineModule, ], - providers: [ - provideMockStore({ - initialState: createState(createDebuggerState()), - }), - DebuggerContainer, - ], + providers: [provideMockStore(), DebuggerContainer], }).compileComponents(); store = TestBed.get(Store); dispatchSpy = spyOn(store, 'dispatch'); @@ -142,7 +137,6 @@ describe('Source Files Container', () => { file_path: '/home/user/main.py', lineno: 3, }); - store.refreshState(); fixture.detectChanges(); await fixture.whenStable(); @@ -203,7 +197,6 @@ describe('Source Files Container', () => { file_path: '/home/user/main.py', lineno: 2, }); - store.refreshState(); fixture.detectChanges(); await fixture.whenStable(); From de7fc3b28b0793e6ae2d736a150f665f066cf052 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 27 Mar 2020 18:04:54 -0400 Subject: [PATCH 17/21] Refactor-split tests for SourceCodeComponent and SourceFilesContainer --- .../debugger_v2/tf_debugger_v2_plugin/BUILD | 1 + .../views/source_code/BUILD | 30 +++++ .../source_code/source_code_component.ts | 15 ++- .../source_code/source_code_component_test.ts | 125 ++++++++++++++++++ .../views/source_code/testing.ts | 68 ++++++++++ .../views/source_files/BUILD | 1 + .../source_files/source_files_component.ts | 8 ++ .../source_files_container_test.ts | 117 ++-------------- 8 files changed, 252 insertions(+), 113 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component_test.ts create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD index 8631e98b09..c7f467a8a7 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD @@ -76,6 +76,7 @@ tf_ng_web_test_suite( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects:debugger_effects_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debugger_store_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts:alerts_container_test_lib", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_component_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files:source_files_container_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline:timeline_test", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD index 54d2a77548..90e02d8431 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD @@ -44,3 +44,33 @@ tf_ts_library( "@npm//@types/requirejs", ], ) + +tf_ts_library( + name = "testing", + srcs = [ + "testing.ts", + ], + deps = [ + ":load_monaco", + "@npm//@types/jasmine", + ], +) + +tf_ts_library( + name = "source_code_component_test_lib", + testonly = True, + srcs = [ + "source_code_component_test.ts", + ], + tsconfig = "//:tsconfig-test", + deps = [ + ":source_code", + ":testing", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:debugger_v2", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing", + "//tensorboard/webapp/angular:expect_angular_core_testing", + "@npm//@angular/compiler", + "@npm//@angular/core", + "@npm//@types/jasmine", + ], +) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index 3140797183..53d44d6a5b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -90,7 +90,6 @@ export class SourceCodeComponent { this.editor.setValue(value); } } - // TODO(cais): Use `this.lines` vs. `changes.focusedLineno.currentValue`. if ( changes.focusedLineno && changes.focusedLineno.currentValue && @@ -98,14 +97,19 @@ export class SourceCodeComponent { this.editor !== null ) { this.editor.revealLineInCenter( - this.focusedLineno, + changes.focusedLineno.currentValue, monaco.editor.ScrollType.Smooth ); const lineLength = currentLines[changes.focusedLineno.currentValue - 1].length; this.decorations = this.editor.deltaDecorations(this.decorations, [ { - range: new monaco.Range(this.focusedLineno, 1, this.focusedLineno, 1), + range: new monaco.Range( + changes.focusedLineno.currentValue, + 1, + changes.focusedLineno.currentValue, + 1 + ), options: { isWholeLine: true, linesDecorationsClassName: 'highlight-gutter', @@ -113,9 +117,9 @@ export class SourceCodeComponent { }, { range: new monaco.Range( - this.focusedLineno, + changes.focusedLineno.currentValue, 1, - this.focusedLineno, + changes.focusedLineno.currentValue, lineLength + 1 ), options: { @@ -128,7 +132,6 @@ export class SourceCodeComponent { @HostListener('window:resize', ['$event']) onResize(event: Event) { - console.log('onResize'); // DEBUG if (this.editor !== null) { this.editor.layout(); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component_test.ts new file mode 100644 index 0000000000..1ef06f85c8 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component_test.ts @@ -0,0 +1,125 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +/** + * Unit tests for the the Source Files component and container. + */ +import {SimpleChange} from '@angular/core'; +import {TestBed} from '@angular/core/testing'; + +import {SourceCodeComponent} from './source_code_component'; +import { + editorSpy, + fakeMonaco, + loadMonacoSpy, + setUpMonacoFakes, + tearDownMonacoFakes, +} from './testing'; + +describe('Source Code Component', () => { + beforeEach(async () => { + setUpMonacoFakes(); + await TestBed.configureTestingModule({ + declarations: [SourceCodeComponent], + }).compileComponents(); + }); + + afterEach(() => { + tearDownMonacoFakes(); + }); + + const lines1 = ['import tensorflow as tf', '', 'print("hello, world")']; + const lines2 = [ + 'model = tf.keras.Sequential', + 'model.add(tf.keras.layers.Dense(1))', + ]; + + it('renders a file and change to a new file', async () => { + const fixture = TestBed.createComponent(SourceCodeComponent); + const component = fixture.componentInstance; + await component.ngOnChanges({ + lines: new SimpleChange(null, lines1, true), + focusedLineno: new SimpleChange(null, 3, true), + }); + component.lines = lines1; + component.focusedLineno = 3; + + expect(loadMonacoSpy).toHaveBeenCalledTimes(1); + // Initial rendering of code uses monaco editor's constructor instead of + // using `setValue()`. + expect(editorSpy.setValue).not.toHaveBeenCalled(); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(1); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 3, + fakeMonaco.editor.ScrollType.Smooth + ); + expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(1); + + await component.ngOnChanges({ + lines: new SimpleChange(lines1, lines2, false), + focusedLineno: new SimpleChange(3, 1, false), + }); + + expect(editorSpy.setValue).toHaveBeenCalledTimes(1); + expect(editorSpy.setValue).toHaveBeenCalledWith( + 'model = tf.keras.Sequential\nmodel.add(tf.keras.layers.Dense(1))' + ); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 1, + fakeMonaco.editor.ScrollType.Smooth + ); + expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(2); + }); + + it('switches to a different line in the same file', async () => { + const fixture = TestBed.createComponent(SourceCodeComponent); + const component = fixture.componentInstance; + await component.ngOnChanges({ + lines: new SimpleChange(null, lines1, true), + focusedLineno: new SimpleChange(null, 2, true), + }); + component.lines = lines1; + component.focusedLineno = 2; + await component.ngOnChanges({ + focusedLineno: new SimpleChange(2, 1, false), + }); + + // setValue() shouldn't have been called because there is no change in file + // content. + expect(editorSpy.setValue).toHaveBeenCalledTimes(0); + expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); + // This is the call for the old lineno. + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 2, + fakeMonaco.editor.ScrollType.Smooth + ); + // This is the call for the new lineno. + expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + 1, + fakeMonaco.editor.ScrollType.Smooth + ); + }); + + it('calls monaco editor layout() on resize', async () => { + const fixture = TestBed.createComponent(SourceCodeComponent); + const component = fixture.componentInstance; + await component.ngOnChanges({ + lines: new SimpleChange(null, lines1, true), + focusedLineno: new SimpleChange(null, 3, true), + }); + component.onResize(new Event('resize')); + expect(editorSpy.layout).toHaveBeenCalledTimes(1); + }); +}); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts new file mode 100644 index 0000000000..8203b1dc80 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts @@ -0,0 +1,68 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +/** + * Testing utilities (fakes and spies) for testing monaco-editor-based source + * code components. + */ + +import * as loadMonacoShim from './load_monaco_shim'; + +export class FakeRange { + constructor( + readonly startLineNumber: number, + readonly startColumn: number, + readonly endLineNumber: number, + readonly endColumn: number + ) {} +} + +export let loadMonacoSpy: jasmine.Spy; +// TODO(cais): Explore better typing by depending on 3rd-party libraries. +export let editorSpy: jasmine.SpyObj; +export let fakeMonaco: any; + +export function setUpMonacoFakes() { + async function fakeLoadMonaco() { + fakeMonaco = { + editor: { + create: () => { + editorSpy = jasmine.createSpyObj('editorSpy', [ + 'deltaDecorations', + 'layout', + 'revealLineInCenter', + 'setValue', + ]); + return editorSpy; + }, + ScrollType: { + Immediate: 1, + Smooth: 0, + }, + }, + Range: FakeRange, + }; + loadMonacoShim.windowWithRequireAndMonaco.monaco = fakeMonaco; + } + loadMonacoSpy = spyOn(loadMonacoShim, 'loadMonaco').and.callFake( + fakeLoadMonaco + ); +} + +export function tearDownMonacoFakes() { + if (loadMonacoShim.windowWithRequireAndMonaco.monaco !== undefined) { + delete loadMonacoShim.windowWithRequireAndMonaco.monaco; + } +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD index ec0388b5ac..2d926f3a89 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/BUILD @@ -44,6 +44,7 @@ tf_ts_library( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:load_monaco", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:testing", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", "//tensorboard/webapp/angular:expect_angular_core_testing", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts index 8254720891..83fa723850 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ts @@ -16,6 +16,14 @@ import {Component, Input} from '@angular/core'; import {SourceFileContent, SourceLineSpec} from '../../store/debugger_types'; +/** + * Renders the content of source file(s). + * + * Unlike `SourceCodeComponent`, which displays only the content of a single + * source-code file, `SourceFilesComponent`is aware of the meta-informaton about + * the files being displayed, such their file paths. Such meta-information is + * displayed by this component. + */ @Component({ selector: 'source-files-component', templateUrl: './source_files_component.ng.html', diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts index 919d0c62b4..0d114438c2 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_container_test.ts @@ -29,7 +29,7 @@ import {createDebuggerState, createState} from '../../testing'; import {AlertsModule} from '../alerts/alerts_module'; import {ExecutionDataModule} from '../execution_data/execution_data_module'; import {InactiveModule} from '../inactive/inactive_module'; -import * as loadMonacoShim from '../source_code/load_monaco_shim'; +import {setUpMonacoFakes, tearDownMonacoFakes} from '../source_code/testing'; import {StackTraceModule} from '../stack_trace/stack_trace_module'; import { getFocusedSourceFileContent, @@ -45,51 +45,6 @@ describe('Source Files Container', () => { let store: MockStore; let dispatchSpy: jasmine.Spy; - class FakeRange { - constructor( - readonly startLineNumber: number, - readonly startColumn: number, - readonly endLineNumber: number, - readonly endColumn: number - ) {} - } - - let loadMonacoSpy: jasmine.Spy; - // TODO(cais): Explore better typing by depending on 3rd-party libraries. - let editorSpy: jasmine.SpyObj; - let monaco: any; - function setUpMonacoFakes() { - async function fakeLoadMonaco() { - monaco = { - editor: { - create: () => { - editorSpy = jasmine.createSpyObj('editorSpy', [ - 'deltaDecorations', - 'revealLineInCenter', - 'setValue', - ]); - return editorSpy; - }, - ScrollType: { - Immediate: 1, - Smooth: 0, - }, - }, - Range: FakeRange, - }; - loadMonacoShim.windowWithRequireAndMonaco.monaco = monaco; - } - loadMonacoSpy = spyOn(loadMonacoShim, 'loadMonaco').and.callFake( - fakeLoadMonaco - ); - } - - function tearDownMonacoFakes() { - if (loadMonacoShim.windowWithRequireAndMonaco.monaco !== undefined) { - delete loadMonacoShim.windowWithRequireAndMonaco.monaco; - } - } - beforeEach(async () => { setUpMonacoFakes(); await TestBed.configureTestingModule({ @@ -124,6 +79,11 @@ describe('Source Files Container', () => { expect(noFileSelectedElement.nativeElement.innerText).toBe( '(No file selected)' ); + + const sourceCodeElements = fixture.debugElement.queryAll( + By.css('source-code-component') + ); + expect(sourceCodeElements.length).toBe(0); }); it('renders file path and editor when a file is focused on', async () => { @@ -142,14 +102,11 @@ describe('Source Files Container', () => { let fileLabelElement = fixture.debugElement.query(By.css('.file-label')); expect(fileLabelElement.nativeElement.innerText).toBe('/home/user/main.py'); - expect(loadMonacoSpy).toHaveBeenCalledTimes(1); - expect(editorSpy.setValue).not.toHaveBeenCalled(); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(1); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( - 3, - monaco.editor.ScrollType.Smooth + + const sourceCodeElements = fixture.debugElement.queryAll( + By.css('source-code-component') ); - expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(1); + expect(sourceCodeElements.length).toBe(1); // Check the behavior when a new file is focused on. store.overrideSelector(getFocusedSourceFileContent, { @@ -172,59 +129,5 @@ describe('Source Files Container', () => { expect(fileLabelElement.nativeElement.innerText).toBe( '/home/user/model.py' ); - // Switching to a different file relies on setValue() to render the code - // of the new file. - expect(editorSpy.setValue).toHaveBeenCalledTimes(1); - expect(editorSpy.setValue).toHaveBeenCalledWith( - 'model = tf.keras.Sequential\nmodel.add(tf.keras.layers.Dense(1))' - ); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( - 1, - monaco.editor.ScrollType.Smooth - ); - expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(2); - }); - - it('switching to a different line in the same file', async () => { - const fixture = TestBed.createComponent(SourceFilesContainer); - store.overrideSelector(getFocusedSourceFileContent, { - loadState: DataLoadState.LOADED, - lines: ['import tensorflow as tf', '', 'print("hello, world")'], - }); - store.overrideSelector(getFocusedSourceLineSpec, { - host_name: 'localhost', - file_path: '/home/user/main.py', - lineno: 2, - }); - fixture.detectChanges(); - await fixture.whenStable(); - - // Check the behavior when a new file is focused on. - store.overrideSelector(getFocusedSourceLineSpec, { - host_name: 'localhost', - file_path: '/home/user/main.py', - lineno: 1, // Focusing on a different line of the same file. - }); - store.refreshState(); - fixture.detectChanges(); - await fixture.whenStable(); - - const fileLabelElement = fixture.debugElement.query(By.css('.file-label')); - expect(fileLabelElement.nativeElement.innerText).toBe('/home/user/main.py'); - // setValue() shouldn't have been called because there is no change in file - // content. - expect(editorSpy.setValue).toHaveBeenCalledTimes(0); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); - // This is the call for the old lineno. - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( - 2, - monaco.editor.ScrollType.Smooth - ); - // This is the call for the new lineno. - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( - 1, - monaco.editor.ScrollType.Smooth - ); }); }); From 18df880c7298159e0198ffad7c7ee53b5df7a475 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 31 Mar 2020 16:58:51 -0400 Subject: [PATCH 18/21] Add debounce to resize-triggered re-layout; Add SourceCodeContainer Unit tests are revised accordingly. --- .../debugger_v2/tf_debugger_v2_plugin/BUILD | 2 +- .../views/source_code/BUILD | 8 +- .../source_code/source_code_component.ts | 115 ++++++++++-------- .../source_code/source_code_container.ts | 65 ++++++++++ ..._test.ts => source_code_container_test.ts} | 73 +++++++++-- .../views/source_code/source_code_module.ts | 7 +- .../source_files/source_files_component.css | 2 +- .../source_files_component.ng.html | 4 +- 8 files changed, 210 insertions(+), 66 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts rename tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/{source_code_component_test.ts => source_code_container_test.ts} (68%) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD index c7f467a8a7..98f679c7be 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD @@ -76,7 +76,7 @@ tf_ng_web_test_suite( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects:debugger_effects_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debugger_store_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts:alerts_container_test_lib", - "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_component_test_lib", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_container_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files:source_files_container_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline:timeline_test", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD index 90e02d8431..fe1749c20a 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD @@ -9,6 +9,7 @@ ng_module( name = "source_code", srcs = [ "source_code_component.ts", + "source_code_container.ts", "source_code_module.ts", ], assets = [ @@ -17,7 +18,9 @@ ng_module( ], deps = [ ":load_monaco", + "@npm//@angular/common", "@npm//@angular/core", + "@npm//rxjs", ], ) @@ -57,13 +60,14 @@ tf_ts_library( ) tf_ts_library( - name = "source_code_component_test_lib", + name = "source_code_container_test_lib", testonly = True, srcs = [ - "source_code_component_test.ts", + "source_code_container_test.ts", ], tsconfig = "//:tsconfig-test", deps = [ + ":load_monaco", # TODO(cais): Clean up. ":source_code", ":testing", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:debugger_v2", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index 53d44d6a5b..ceae33b4c9 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -16,49 +16,38 @@ import { ChangeDetectionStrategy, Component, ElementRef, - HostListener, Input, SimpleChanges, ViewChild, + OnInit, } from '@angular/core'; +import {fromEvent, interval} from 'rxjs'; +import {debounce, tap} from 'rxjs/operators'; -import { - loadMonaco, - WindowWithRequireAndMonaco, -} from '../source_code/load_monaco_shim'; - -const windowWithRequireAndMonaco: WindowWithRequireAndMonaco = window; +/** @typehack */ import * as _typeHackRxjs from 'rxjs'; const DEFAULT_CODE_LANGUAGE = 'python'; const DEFAULT_CODE_FONT_SIZE = 10; -/** - * SoureCodeComponent displays the content of a source-code file. - * - * It displays the code with visual features including syntax highlighting. - * It additionally provides functionalities to: - * - Scroll to and highlight a given line by its line number. - * - * TODO(cais): Add support for line decoration and symbol decoration. - * - * Unlike SourceFilesComponent, SourceCodeComponent handles only one file at a - * time. - */ +const RESIZE_DEBOUNCE_INTERAVL_MS = 50; + @Component({ selector: 'source-code-component', templateUrl: './source_code_component.ng.html', styleUrls: ['./source_code_component.css'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SourceCodeComponent { - // Lines of the source-code file, split at line breaks. +export class SourceCodeComponent implements OnInit { @Input() lines: string[] | null = null; // TODO(cais): Add spinner for `null`. - // Line number to scroll to and highlight, 1-based. @Input() focusedLineno: number | null = null; + // TODO(cais): Explore better typing by depending on external libraries. + @Input() + monaco: any | null = null; + @ViewChild('codeViewerContainer', {static: true, read: ElementRef}) private readonly codeViewerContainer!: ElementRef; @@ -66,15 +55,35 @@ export class SourceCodeComponent { private decorations: string[] = []; + ngOnInit(): void { + // Listen to window resize event. When resize happens, re-layout + // monaco editor. Do this with `debounce()` to prevent re-layouting + // at too high a rate. + fromEvent(window, 'resize') + .pipe( + debounce(() => interval(RESIZE_DEBOUNCE_INTERAVL_MS)), + tap(() => { + if (this.editor !== null) { + this.editor.layout(); + } + }) + ) + .subscribe(); + } + async ngOnChanges(changes: SimpleChanges): Promise { - await loadMonaco(); - const monaco = windowWithRequireAndMonaco.monaco; - let currentLines: string[] | null = this.lines; - if (changes.lines && changes.lines.currentValue !== null) { - currentLines = changes.lines.currentValue; - const value = changes.lines.currentValue.join('\n'); + if (this.monaco === null) { + return; + } + const currentLines: string[] | null = changes.monaco + ? this.lines + : changes.lines + ? changes.lines.currentValue + : null; + if (currentLines) { + const value = currentLines.join('\n'); if (this.editor === null) { - this.editor = monaco.editor.create( + this.editor = this.monaco.editor.create( this.codeViewerContainer.nativeElement, { value, @@ -90,24 +99,33 @@ export class SourceCodeComponent { this.editor.setValue(value); } } + + const currentFocusedLineno: number | null = changes.monaco + ? this.focusedLineno + : changes.focusedLineno + ? changes.focusedLineno.currentValue + : null; if ( - changes.focusedLineno && - changes.focusedLineno.currentValue && - currentLines && - this.editor !== null + currentFocusedLineno && + this.lines && + this.monaco !== null + // changes.focusedLineno && + // changes.focusedLineno.currentValue && + // currentLines && + // this.monaco !== null && + // this.editor !== null ) { this.editor.revealLineInCenter( - changes.focusedLineno.currentValue, - monaco.editor.ScrollType.Smooth + currentFocusedLineno, + this.monaco.editor.ScrollType.Smooth ); - const lineLength = - currentLines[changes.focusedLineno.currentValue - 1].length; + const lineLength = this.lines[currentFocusedLineno - 1].length; this.decorations = this.editor.deltaDecorations(this.decorations, [ { - range: new monaco.Range( - changes.focusedLineno.currentValue, + range: new this.monaco.Range( + currentFocusedLineno, 1, - changes.focusedLineno.currentValue, + currentFocusedLineno, 1 ), options: { @@ -116,10 +134,10 @@ export class SourceCodeComponent { }, }, { - range: new monaco.Range( - changes.focusedLineno.currentValue, + range: new this.monaco.Range( + currentFocusedLineno, 1, - changes.focusedLineno.currentValue, + currentFocusedLineno, lineLength + 1 ), options: { @@ -129,11 +147,8 @@ export class SourceCodeComponent { ]); } } - - @HostListener('window:resize', ['$event']) - onResize(event: Event) { - if (this.editor !== null) { - this.editor.layout(); - } - } } + +export const TEST_ONLY = { + RESIZE_DEBOUNCE_INTERAVL_MS, +}; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts new file mode 100644 index 0000000000..0164526274 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts @@ -0,0 +1,65 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +import {Component, Input} from '@angular/core'; +import {from} from 'rxjs'; +import {map} from 'rxjs/operators'; + +import {loadMonaco, WindowWithRequireAndMonaco} from './load_monaco_shim'; + +/** @typehack */ import * as _typeHackRxjs from 'rxjs'; + +const windowWithRequireAndMonaco: WindowWithRequireAndMonaco = window; + +/** + * SourceCodeContainer displays the content of a source-code file. + * + * It displays the code with visual features including syntax highlighting. + * It additionally provides functionalities to: + * - Scroll to and highlight a given line by its line number. + * + * TODO(cais): Add support for line decoration and symbol decoration. + * + * Unlike SourceFilesComponent, SourceCodeContainer handles only one file at a + * time. + */ +@Component({ + selector: 'tf-debugger-v2-source-code', + template: ` + + `, +}) +export class SourceCodeContainer { + // Lines of the source-code file, split at line breaks. + @Input() + lines: string[] | null = null; // TODO(cais): Add spinner for `null`. + + // Line number to scroll to and highlight, 1-based. + @Input() + focusedLineno: number | null = null; + + monaco$: any | null = null; + + ngOnInit(): void { + this.monaco$ = from(loadMonaco()).pipe( + map(() => windowWithRequireAndMonaco.monaco) + ); + } + + constructor() {} +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container_test.ts similarity index 68% rename from tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component_test.ts rename to tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container_test.ts index 1ef06f85c8..a24c007069 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container_test.ts @@ -18,7 +18,8 @@ limitations under the License. import {SimpleChange} from '@angular/core'; import {TestBed} from '@angular/core/testing'; -import {SourceCodeComponent} from './source_code_component'; +import {SourceCodeComponent, TEST_ONLY} from './source_code_component'; +import {SourceCodeContainer} from './source_code_container'; import { editorSpy, fakeMonaco, @@ -26,12 +27,13 @@ import { setUpMonacoFakes, tearDownMonacoFakes, } from './testing'; +import * as loadMonacoShim from './load_monaco_shim'; describe('Source Code Component', () => { beforeEach(async () => { setUpMonacoFakes(); await TestBed.configureTestingModule({ - declarations: [SourceCodeComponent], + declarations: [SourceCodeComponent, SourceCodeContainer], }).compileComponents(); }); @@ -48,14 +50,23 @@ describe('Source Code Component', () => { it('renders a file and change to a new file', async () => { const fixture = TestBed.createComponent(SourceCodeComponent); const component = fixture.componentInstance; + component.lines = lines1; + component.focusedLineno = 3; await component.ngOnChanges({ lines: new SimpleChange(null, lines1, true), focusedLineno: new SimpleChange(null, 3, true), }); - component.lines = lines1; - component.focusedLineno = 3; + // Simlulate loading monaco and setting the `monaco` input after loading. + await loadMonacoShim.loadMonaco(); + component.monaco = loadMonacoShim.windowWithRequireAndMonaco.monaco; + await component.ngOnChanges({ + monaco: new SimpleChange( + null, + loadMonacoShim.windowWithRequireAndMonaco.monaco, + true + ), + }); - expect(loadMonacoSpy).toHaveBeenCalledTimes(1); // Initial rendering of code uses monaco editor's constructor instead of // using `setValue()`. expect(editorSpy.setValue).not.toHaveBeenCalled(); @@ -66,6 +77,8 @@ describe('Source Code Component', () => { ); expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(1); + component.lines = lines2; + component.focusedLineno = 1; await component.ngOnChanges({ lines: new SimpleChange(lines1, lines2, false), focusedLineno: new SimpleChange(3, 1, false), @@ -86,12 +99,14 @@ describe('Source Code Component', () => { it('switches to a different line in the same file', async () => { const fixture = TestBed.createComponent(SourceCodeComponent); const component = fixture.componentInstance; + await loadMonacoShim.loadMonaco(); + component.monaco = loadMonacoShim.windowWithRequireAndMonaco.monaco; + component.lines = lines1; + component.focusedLineno = 2; await component.ngOnChanges({ lines: new SimpleChange(null, lines1, true), focusedLineno: new SimpleChange(null, 2, true), }); - component.lines = lines1; - component.focusedLineno = 2; await component.ngOnChanges({ focusedLineno: new SimpleChange(2, 1, false), }); @@ -112,14 +127,56 @@ describe('Source Code Component', () => { ); }); + function sleep(durationMs: number): Promise { + return new Promise((resolve) => { + setInterval(() => { + resolve(); + }, durationMs); + }); + } + it('calls monaco editor layout() on resize', async () => { const fixture = TestBed.createComponent(SourceCodeComponent); const component = fixture.componentInstance; + component.ngOnInit(); + component.lines = lines1; + component.focusedLineno = 3; await component.ngOnChanges({ lines: new SimpleChange(null, lines1, true), focusedLineno: new SimpleChange(null, 3, true), }); - component.onResize(new Event('resize')); + await loadMonacoShim.loadMonaco(); + component.monaco = loadMonacoShim.windowWithRequireAndMonaco.monaco; + await component.ngOnChanges({ + monaco: new SimpleChange( + null, + loadMonacoShim.windowWithRequireAndMonaco.monaco, + true + ), + }); + + window.dispatchEvent(new Event('resize')); + await sleep(TEST_ONLY.RESIZE_DEBOUNCE_INTERAVL_MS); expect(editorSpy.layout).toHaveBeenCalledTimes(1); }); }); + +describe('Source Code Container', () => { + beforeEach(async () => { + setUpMonacoFakes(); + await TestBed.configureTestingModule({ + declarations: [SourceCodeComponent, SourceCodeContainer], + }).compileComponents(); + }); + + afterEach(() => { + tearDownMonacoFakes(); + }); + + it('calls loadMonaco() on ngOnInit()', () => { + const fixture = TestBed.createComponent(SourceCodeContainer); + const component = fixture.componentInstance; + component.ngOnInit(); + expect(loadMonacoSpy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts index 40a5e32c1b..b17a6aaf46 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_module.ts @@ -13,12 +13,15 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; import {SourceCodeComponent} from './source_code_component'; +import {SourceCodeContainer} from './source_code_container'; @NgModule({ - declarations: [SourceCodeComponent], - exports: [SourceCodeComponent], + declarations: [SourceCodeComponent, SourceCodeContainer], + imports: [CommonModule], + exports: [SourceCodeContainer], }) export class SourceCodeModule {} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css index 7493abf9c9..c58b545de9 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.css @@ -51,7 +51,7 @@ limitations under the License. vertical-align: top; } -source-code-component { +tf-debugger-v2-source-code { flex-grow: 1; width: 100%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html index 7ddff7fdba..ca5db69b0c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files/source_files_component.ng.html @@ -36,12 +36,12 @@
- - +
From e9d48a199a44d6affdab46af9fe9f2c3fb8dfb14 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 31 Mar 2020 22:40:14 -0400 Subject: [PATCH 19/21] Remove cruft comment --- .../debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD index fe1749c20a..8053bdd087 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/BUILD @@ -67,7 +67,7 @@ tf_ts_library( ], tsconfig = "//:tsconfig-test", deps = [ - ":load_monaco", # TODO(cais): Clean up. + ":load_monaco", ":source_code", ":testing", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:debugger_v2", From 88eacfdbe56a5b138efe9297f0d10ca6b9d8d5d1 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 31 Mar 2020 23:15:49 -0400 Subject: [PATCH 20/21] Changes needed for fixing sync - Use string indexing in `ngOnChanges()`. - Add msissing dependency for views/stack_trace/BUILD - Remove unreachable typing - Use const export from source_code/testing.ts --- .../source_code/source_code_component.ts | 23 +++---- .../source_code/source_code_container.ts | 7 ++- .../source_code/source_code_container_test.ts | 62 ++++++++----------- .../views/source_code/testing.ts | 27 +++++--- .../views/stack_trace/BUILD | 1 + 5 files changed, 56 insertions(+), 64 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index ceae33b4c9..b87eed0ea2 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -75,10 +75,10 @@ export class SourceCodeComponent implements OnInit { if (this.monaco === null) { return; } - const currentLines: string[] | null = changes.monaco + const currentLines: string[] | null = changes['monaco'] ? this.lines - : changes.lines - ? changes.lines.currentValue + : changes['lines'] + ? changes['lines'].currentValue : null; if (currentLines) { const value = currentLines.join('\n'); @@ -100,21 +100,12 @@ export class SourceCodeComponent implements OnInit { } } - const currentFocusedLineno: number | null = changes.monaco + const currentFocusedLineno: number | null = changes['monaco'] ? this.focusedLineno - : changes.focusedLineno - ? changes.focusedLineno.currentValue + : changes['focusedLineno'] + ? changes['focusedLineno'].currentValue : null; - if ( - currentFocusedLineno && - this.lines && - this.monaco !== null - // changes.focusedLineno && - // changes.focusedLineno.currentValue && - // currentLines && - // this.monaco !== null && - // this.editor !== null - ) { + if (currentFocusedLineno && this.lines && this.monaco !== null) { this.editor.revealLineInCenter( currentFocusedLineno, this.monaco.editor.ScrollType.Smooth diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts index 0164526274..7601ea2089 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container.ts @@ -16,11 +16,12 @@ import {Component, Input} from '@angular/core'; import {from} from 'rxjs'; import {map} from 'rxjs/operators'; -import {loadMonaco, WindowWithRequireAndMonaco} from './load_monaco_shim'; +import {loadMonaco} from './load_monaco_shim'; -/** @typehack */ import * as _typeHackRxjs from 'rxjs'; +/** @typehack */ import * as _typeHackRxjwindowWithRequireAndMonacos from 'rxjs'; -const windowWithRequireAndMonaco: WindowWithRequireAndMonaco = window; +// TODO(cais): Explore better typing by depending on external libraries. +const windowWithRequireAndMonaco: any = window; /** * SourceCodeContainer displays the content of a source-code file. diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container_test.ts index a24c007069..0c29d224b8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_container_test.ts @@ -21,11 +21,11 @@ import {TestBed} from '@angular/core/testing'; import {SourceCodeComponent, TEST_ONLY} from './source_code_component'; import {SourceCodeContainer} from './source_code_container'; import { - editorSpy, - fakeMonaco, - loadMonacoSpy, + fakes, setUpMonacoFakes, + spies, tearDownMonacoFakes, + windowWithRequireAndMonaco, } from './testing'; import * as loadMonacoShim from './load_monaco_shim'; @@ -58,24 +58,20 @@ describe('Source Code Component', () => { }); // Simlulate loading monaco and setting the `monaco` input after loading. await loadMonacoShim.loadMonaco(); - component.monaco = loadMonacoShim.windowWithRequireAndMonaco.monaco; + component.monaco = windowWithRequireAndMonaco.monaco; await component.ngOnChanges({ - monaco: new SimpleChange( - null, - loadMonacoShim.windowWithRequireAndMonaco.monaco, - true - ), + monaco: new SimpleChange(null, windowWithRequireAndMonaco.monaco, true), }); // Initial rendering of code uses monaco editor's constructor instead of // using `setValue()`. - expect(editorSpy.setValue).not.toHaveBeenCalled(); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(1); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + expect(spies.editorSpy.setValue).not.toHaveBeenCalled(); + expect(spies.editorSpy.revealLineInCenter).toHaveBeenCalledTimes(1); + expect(spies.editorSpy.revealLineInCenter).toHaveBeenCalledWith( 3, - fakeMonaco.editor.ScrollType.Smooth + fakes.fakeMonaco.editor.ScrollType.Smooth ); - expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(1); + expect(spies.editorSpy.deltaDecorations).toHaveBeenCalledTimes(1); component.lines = lines2; component.focusedLineno = 1; @@ -84,23 +80,23 @@ describe('Source Code Component', () => { focusedLineno: new SimpleChange(3, 1, false), }); - expect(editorSpy.setValue).toHaveBeenCalledTimes(1); - expect(editorSpy.setValue).toHaveBeenCalledWith( + expect(spies.editorSpy.setValue).toHaveBeenCalledTimes(1); + expect(spies.editorSpy.setValue).toHaveBeenCalledWith( 'model = tf.keras.Sequential\nmodel.add(tf.keras.layers.Dense(1))' ); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + expect(spies.editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); + expect(spies.editorSpy.revealLineInCenter).toHaveBeenCalledWith( 1, - fakeMonaco.editor.ScrollType.Smooth + fakes.fakeMonaco.editor.ScrollType.Smooth ); - expect(editorSpy.deltaDecorations).toHaveBeenCalledTimes(2); + expect(spies.editorSpy.deltaDecorations).toHaveBeenCalledTimes(2); }); it('switches to a different line in the same file', async () => { const fixture = TestBed.createComponent(SourceCodeComponent); const component = fixture.componentInstance; await loadMonacoShim.loadMonaco(); - component.monaco = loadMonacoShim.windowWithRequireAndMonaco.monaco; + component.monaco = windowWithRequireAndMonaco.monaco; component.lines = lines1; component.focusedLineno = 2; await component.ngOnChanges({ @@ -113,17 +109,17 @@ describe('Source Code Component', () => { // setValue() shouldn't have been called because there is no change in file // content. - expect(editorSpy.setValue).toHaveBeenCalledTimes(0); - expect(editorSpy.revealLineInCenter).toHaveBeenCalledTimes(2); + expect(spies.editorSpy!.setValue).toHaveBeenCalledTimes(0); + expect(spies.editorSpy!.revealLineInCenter).toHaveBeenCalledTimes(2); // This is the call for the old lineno. - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + expect(spies.editorSpy!.revealLineInCenter).toHaveBeenCalledWith( 2, - fakeMonaco.editor.ScrollType.Smooth + fakes.fakeMonaco.editor.ScrollType.Smooth ); // This is the call for the new lineno. - expect(editorSpy.revealLineInCenter).toHaveBeenCalledWith( + expect(spies.editorSpy.revealLineInCenter).toHaveBeenCalledWith( 1, - fakeMonaco.editor.ScrollType.Smooth + fakes.fakeMonaco.editor.ScrollType.Smooth ); }); @@ -146,18 +142,14 @@ describe('Source Code Component', () => { focusedLineno: new SimpleChange(null, 3, true), }); await loadMonacoShim.loadMonaco(); - component.monaco = loadMonacoShim.windowWithRequireAndMonaco.monaco; + component.monaco = windowWithRequireAndMonaco.monaco; await component.ngOnChanges({ - monaco: new SimpleChange( - null, - loadMonacoShim.windowWithRequireAndMonaco.monaco, - true - ), + monaco: new SimpleChange(null, windowWithRequireAndMonaco.monaco, true), }); window.dispatchEvent(new Event('resize')); await sleep(TEST_ONLY.RESIZE_DEBOUNCE_INTERAVL_MS); - expect(editorSpy.layout).toHaveBeenCalledTimes(1); + expect(spies.editorSpy!.layout).toHaveBeenCalledTimes(1); }); }); @@ -177,6 +169,6 @@ describe('Source Code Container', () => { const fixture = TestBed.createComponent(SourceCodeContainer); const component = fixture.componentInstance; component.ngOnInit(); - expect(loadMonacoSpy).toHaveBeenCalledTimes(1); + expect(spies.loadMonacoSpy!).toHaveBeenCalledTimes(1); }); }); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts index 8203b1dc80..be09133eb7 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/testing.ts @@ -29,23 +29,30 @@ export class FakeRange { ) {} } -export let loadMonacoSpy: jasmine.Spy; // TODO(cais): Explore better typing by depending on 3rd-party libraries. -export let editorSpy: jasmine.SpyObj; -export let fakeMonaco: any; +export const spies: { + loadMonacoSpy?: jasmine.Spy; + editorSpy?: jasmine.SpyObj; +} = {}; + +export const fakes: { + fakeMonaco?: any; +} = {}; + +export const windowWithRequireAndMonaco: any = window; export function setUpMonacoFakes() { async function fakeLoadMonaco() { - fakeMonaco = { + fakes.fakeMonaco = { editor: { create: () => { - editorSpy = jasmine.createSpyObj('editorSpy', [ + spies.editorSpy = jasmine.createSpyObj('editorSpy', [ 'deltaDecorations', 'layout', 'revealLineInCenter', 'setValue', ]); - return editorSpy; + return spies.editorSpy; }, ScrollType: { Immediate: 1, @@ -54,15 +61,15 @@ export function setUpMonacoFakes() { }, Range: FakeRange, }; - loadMonacoShim.windowWithRequireAndMonaco.monaco = fakeMonaco; + windowWithRequireAndMonaco.monaco = fakes.fakeMonaco; } - loadMonacoSpy = spyOn(loadMonacoShim, 'loadMonaco').and.callFake( + spies.loadMonacoSpy = spyOn(loadMonacoShim, 'loadMonaco').and.callFake( fakeLoadMonaco ); } export function tearDownMonacoFakes() { - if (loadMonacoShim.windowWithRequireAndMonaco.monaco !== undefined) { - delete loadMonacoShim.windowWithRequireAndMonaco.monaco; + if (windowWithRequireAndMonaco.monaco !== undefined) { + delete windowWithRequireAndMonaco.monaco; } } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD index 9874bb0b8f..324b8cd6b7 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/BUILD @@ -16,6 +16,7 @@ ng_module( "stack_trace_component.ng.html", ], deps = [ + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code", From e70a18a4cc779b73fd08805df1bb9ffbb1a7a3d9 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 1 Apr 2020 09:07:07 -0400 Subject: [PATCH 21/21] Address comments: remove async; use takeUntil() for resize --- .../source_code/source_code_component.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts index b87eed0ea2..1784ad0033 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code/source_code_component.ts @@ -19,10 +19,11 @@ import { Input, SimpleChanges, ViewChild, + OnDestroy, OnInit, } from '@angular/core'; -import {fromEvent, interval} from 'rxjs'; -import {debounce, tap} from 'rxjs/operators'; +import {fromEvent, interval, Subject} from 'rxjs'; +import {debounce, takeUntil, tap} from 'rxjs/operators'; /** @typehack */ import * as _typeHackRxjs from 'rxjs'; @@ -37,7 +38,7 @@ const RESIZE_DEBOUNCE_INTERAVL_MS = 50; styleUrls: ['./source_code_component.css'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class SourceCodeComponent implements OnInit { +export class SourceCodeComponent implements OnInit, OnDestroy { @Input() lines: string[] | null = null; // TODO(cais): Add spinner for `null`. @@ -55,12 +56,16 @@ export class SourceCodeComponent implements OnInit { private decorations: string[] = []; + private readonly ngUnsubscribe = new Subject(); + ngOnInit(): void { // Listen to window resize event. When resize happens, re-layout - // monaco editor. Do this with `debounce()` to prevent re-layouting + // monaco editor, so its width is always up-to-date with respect to + // the window size. Do this with `debounce()` to prevent re-layouting // at too high a rate. - fromEvent(window, 'resize') + const resizePipe = fromEvent(window, 'resize') .pipe( + takeUntil(this.ngUnsubscribe), debounce(() => interval(RESIZE_DEBOUNCE_INTERAVL_MS)), tap(() => { if (this.editor !== null) { @@ -71,7 +76,12 @@ export class SourceCodeComponent implements OnInit { .subscribe(); } - async ngOnChanges(changes: SimpleChanges): Promise { + ngOnDestroy(): void { + this.ngUnsubscribe.next(); + this.ngUnsubscribe.complete(); + } + + ngOnChanges(changes: SimpleChanges): void { if (this.monaco === null) { return; }