-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Activated flag strictNullInputTypes on Angular 21 #7151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ See the License for the specific language governing permissions and | |
| limitations under the License. | ||
| ==============================================================================*/ | ||
| import {ChangeDetectionStrategy, Component} from '@angular/core'; | ||
| import {createSelector, select, Store} from '@ngrx/store'; | ||
| import {createSelector, Store} from '@ngrx/store'; | ||
| import {alertTypeFocusToggled} from '../../actions'; | ||
| import { | ||
| getAlertsBreakdown, | ||
|
|
@@ -49,40 +49,38 @@ const ALERT_TYPE_TO_DISPLAY_NAME_AND_SYMBOL: { | |
| selector: 'tf-debugger-v2-alerts', | ||
| template: ` | ||
| <alerts-component | ||
| [numAlerts]="numAlerts$ | async" | ||
| [alertsBreakdown]="alertsBreakdown$ | async" | ||
| [focusType]="focusType$ | async" | ||
| [numAlerts]="numAlerts()" | ||
| [alertsBreakdown]="alertsBreakdown()" | ||
| [focusType]="focusType()" | ||
| (onToggleFocusType)="onToggleFocusType($event)" | ||
| > | ||
| </alerts-component> | ||
| `, | ||
| changeDetection: ChangeDetectionStrategy.OnPush, | ||
| }) | ||
| export class AlertsContainer { | ||
| readonly numAlerts$; | ||
| readonly numAlerts; | ||
|
|
||
| readonly alertsBreakdown$; | ||
| readonly alertsBreakdown; | ||
|
|
||
| readonly focusType$; | ||
| readonly focusType; | ||
|
|
||
| constructor(private readonly store: Store<State>) { | ||
| this.numAlerts$ = this.store.pipe(select(getNumAlerts)); | ||
| this.alertsBreakdown$ = this.store.pipe( | ||
| select( | ||
| createSelector(getAlertsBreakdown, (alertsBreakdown) => { | ||
| const alertTypes = Object.keys(alertsBreakdown); | ||
| alertTypes.sort(); | ||
| return alertTypes.map((alertType): AlertTypeDisplay => { | ||
| return { | ||
| type: alertType as AlertType, | ||
| ...ALERT_TYPE_TO_DISPLAY_NAME_AND_SYMBOL[alertType], | ||
| count: alertsBreakdown[alertType], | ||
| }; | ||
| }); | ||
| }) | ||
| ) | ||
| this.numAlerts = this.store.selectSignal(getNumAlerts); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to change it in this PR if you prefer the alternative of adding the type to the variables, but in the future, the recommended pattern is to use inject() and direct assignment of the signals outside of the constructor (and the constructor can likely be removed). |
||
| this.alertsBreakdown = this.store.selectSignal( | ||
| createSelector(getAlertsBreakdown, (alertsBreakdown) => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to change it in this PR, but wondering what you think about these being computed signals instead of a selector defined inline? I guess we'd need to first have a signal for the existing selector and then a separate computed signal for the thing we actually care about... which is a bit annoying. |
||
| const alertTypes = Object.keys(alertsBreakdown); | ||
| alertTypes.sort(); | ||
| return alertTypes.map((alertType): AlertTypeDisplay => { | ||
| return { | ||
| type: alertType as AlertType, | ||
| ...ALERT_TYPE_TO_DISPLAY_NAME_AND_SYMBOL[alertType], | ||
| count: alertsBreakdown[alertType], | ||
| }; | ||
| }); | ||
| }) | ||
| ); | ||
| this.focusType$ = this.store.pipe(select(getAlertsFocusType)); | ||
| this.focusType = this.store.selectSignal(getAlertsFocusType); | ||
| } | ||
|
|
||
| onToggleFocusType(alertType: AlertType) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 {createSelector, select, Store} from '@ngrx/store'; | ||
| import {createSelector, Store} from '@ngrx/store'; | ||
| import {getFocusedExecutionData} from '../../store'; | ||
| import {Execution, State, TensorDebugMode} from '../../store/debugger_types'; | ||
| import {DTYPE_ENUM_TO_NAME} from '../../tf_dtypes'; | ||
|
|
@@ -27,115 +27,96 @@ const UNKNOWN_DTYPE_NAME = 'Unknown dtype'; | |
| template: ` | ||
| <execution-data-component | ||
| [focusedExecutionIndex]="focusedExecutionIndex" | ||
| [focusedExecutionData]="focusedExecutionData$ | async" | ||
| [tensorDebugMode]="tensorDebugMode$ | async" | ||
| [hasDebugTensorValues]="hasDebugTensorValues$ | async" | ||
| [debugTensorValues]="debugTensorValues$ | async" | ||
| [debugTensorDtypes]="debugTensorDtypes$ | async" | ||
| [focusedExecutionData]="focusedExecutionData()" | ||
| [tensorDebugMode]="tensorDebugMode()" | ||
| [hasDebugTensorValues]="hasDebugTensorValues()" | ||
| [debugTensorValues]="debugTensorValues()" | ||
| [debugTensorDtypes]="debugTensorDtypes()" | ||
| ></execution-data-component> | ||
| `, | ||
| }) | ||
| export class ExecutionDataContainer { | ||
| @Input() | ||
| focusedExecutionIndex!: number; | ||
|
|
||
| readonly focusedExecutionData$; | ||
| readonly focusedExecutionData; | ||
|
|
||
| readonly tensorDebugMode$; | ||
| readonly tensorDebugMode; | ||
|
|
||
| readonly hasDebugTensorValues$; | ||
| readonly hasDebugTensorValues; | ||
|
|
||
| readonly debugTensorValues$; | ||
| readonly debugTensorValues; | ||
|
|
||
| readonly debugTensorDtypes$; | ||
| readonly debugTensorDtypes; | ||
|
|
||
| constructor(private readonly store: Store<State>) { | ||
| this.focusedExecutionData$ = this.store.pipe( | ||
| select(getFocusedExecutionData) | ||
| this.focusedExecutionData = this.store.selectSignal( | ||
| getFocusedExecutionData | ||
| ); | ||
| this.tensorDebugMode$ = this.store.pipe( | ||
| select( | ||
| createSelector( | ||
| getFocusedExecutionData, | ||
| (execution: Execution | null) => { | ||
| if (execution === null) { | ||
| return TensorDebugMode.UNSPECIFIED; | ||
| } else { | ||
| return execution.tensor_debug_mode; | ||
| } | ||
| } | ||
| ) | ||
| ) | ||
| this.tensorDebugMode = this.store.selectSignal( | ||
| createSelector(getFocusedExecutionData, (execution: Execution | null) => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one should have more clearly been a computed signal, since we already have a signal for the selector used here. (But again, no need to change it here. I understand you might have just got for a simple code update, especially considering the amount of files modified.) |
||
| if (execution === null) { | ||
| return TensorDebugMode.UNSPECIFIED; | ||
| } else { | ||
| return execution.tensor_debug_mode; | ||
| } | ||
| }) | ||
| ); | ||
| this.hasDebugTensorValues$ = this.store.pipe( | ||
| select( | ||
| createSelector( | ||
| getFocusedExecutionData, | ||
| (execution: Execution | null) => { | ||
| if (execution === null || execution.debug_tensor_values === null) { | ||
| return false; | ||
| } else { | ||
| for (const singleDebugTensorValues of execution.debug_tensor_values) { | ||
| if ( | ||
| singleDebugTensorValues !== null && | ||
| singleDebugTensorValues.length > 0 | ||
| ) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| this.hasDebugTensorValues = this.store.selectSignal( | ||
| createSelector(getFocusedExecutionData, (execution: Execution | null) => { | ||
| if (execution === null || execution.debug_tensor_values === null) { | ||
| return false; | ||
| } else { | ||
| for (const singleDebugTensorValues of execution.debug_tensor_values) { | ||
| if ( | ||
| singleDebugTensorValues !== null && | ||
| singleDebugTensorValues.length > 0 | ||
| ) { | ||
| return true; | ||
| } | ||
| } | ||
| ) | ||
| ) | ||
| return false; | ||
| } | ||
| }) | ||
| ); | ||
| this.debugTensorValues$ = this.store.pipe( | ||
| select( | ||
| createSelector( | ||
| getFocusedExecutionData, | ||
| (execution: Execution | null) => { | ||
| if (execution === null) { | ||
| return null; | ||
| } else { | ||
| return execution.debug_tensor_values; | ||
| } | ||
| } | ||
| ) | ||
| ) | ||
| this.debugTensorValues = this.store.selectSignal( | ||
| createSelector(getFocusedExecutionData, (execution: Execution | null) => { | ||
| if (execution === null) { | ||
| return null; | ||
| } else { | ||
| return execution.debug_tensor_values; | ||
| } | ||
| }) | ||
| ); | ||
| this.debugTensorDtypes$ = this.store.pipe( | ||
| select( | ||
| createSelector( | ||
| getFocusedExecutionData, | ||
| (execution: Execution | null): string[] | null => { | ||
| if (execution === null || execution.debug_tensor_values === null) { | ||
| return null; | ||
| } | ||
| if ( | ||
| execution.tensor_debug_mode !== TensorDebugMode.FULL_HEALTH && | ||
| execution.tensor_debug_mode !== TensorDebugMode.SHAPE | ||
| ) { | ||
| // TODO(cais): Add logic for other TensorDebugModes with dtype info. | ||
| return null; | ||
| } | ||
| const dtypes: string[] = []; | ||
| for (const tensorValue of execution.debug_tensor_values) { | ||
| if (tensorValue === null) { | ||
| dtypes.push(UNKNOWN_DTYPE_NAME); | ||
| } else { | ||
| const dtypeEnum = String( | ||
| execution.tensor_debug_mode === TensorDebugMode.FULL_HEALTH | ||
| ? tensorValue[2] // tensor_debug_mode: FULL_HEALTH | ||
| : tensorValue[1] // tensor_debug_mode: SHAPE | ||
| ); | ||
| dtypes.push( | ||
| DTYPE_ENUM_TO_NAME[dtypeEnum] || UNKNOWN_DTYPE_NAME | ||
| ); | ||
| } | ||
| this.debugTensorDtypes = this.store.selectSignal( | ||
| createSelector( | ||
| getFocusedExecutionData, | ||
| (execution: Execution | null): string[] | null => { | ||
| if (execution === null || execution.debug_tensor_values === null) { | ||
| return null; | ||
| } | ||
| if ( | ||
| execution.tensor_debug_mode !== TensorDebugMode.FULL_HEALTH && | ||
| execution.tensor_debug_mode !== TensorDebugMode.SHAPE | ||
| ) { | ||
| // TODO(cais): Add logic for other TensorDebugModes with dtype info. | ||
| return null; | ||
| } | ||
| const dtypes: string[] = []; | ||
| for (const tensorValue of execution.debug_tensor_values) { | ||
| if (tensorValue === null) { | ||
| dtypes.push(UNKNOWN_DTYPE_NAME); | ||
| } else { | ||
| const dtypeEnum = String( | ||
| execution.tensor_debug_mode === TensorDebugMode.FULL_HEALTH | ||
| ? tensorValue[2] // tensor_debug_mode: FULL_HEALTH | ||
| : tensorValue[1] // tensor_debug_mode: SHAPE | ||
| ); | ||
| dtypes.push(DTYPE_ENUM_TO_NAME[dtypeEnum] || UNKNOWN_DTYPE_NAME); | ||
| } | ||
| return dtypes; | ||
| } | ||
| ) | ||
| return dtypes; | ||
| } | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,13 +35,13 @@ import { | |
| }) | ||
| export class GraphComponent { | ||
| @Input() | ||
| opInfo!: GraphOpInfo; | ||
| opInfo!: GraphOpInfo | null; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this variable have a Is the |
||
|
|
||
| @Input() | ||
| inputOps!: GraphOpInputSpec[]; | ||
| inputOps!: GraphOpInputSpec[] | null; | ||
|
|
||
| @Input() | ||
| consumerOps!: GraphOpConsumerSpec[][]; | ||
| consumerOps!: GraphOpConsumerSpec[][] | null; | ||
|
|
||
| @Output() | ||
| onGraphOpNavigate = new EventEmitter<{graph_id: string; op_name: string}>(); | ||
|
|
@@ -50,14 +50,14 @@ export class GraphComponent { | |
| * Get the ID of the immediately-enclosing graph of the op. | ||
| */ | ||
| get graphId() { | ||
| return this.opInfo.graph_ids[this.opInfo.graph_ids.length - 1]; | ||
| return this.opInfo!.graph_ids[this.opInfo!.graph_ids.length - 1]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we shouldn't be adding these It's possible I'm missing some context. If this is necessary for some reason, let me know. |
||
| } | ||
|
|
||
| /** | ||
| * Total number of consumers of all output tensors of the op. | ||
| */ | ||
| get totalNumConsumers() { | ||
| return this.consumerOps.reduce((count, slotConsumers) => { | ||
| return this.consumerOps!.reduce((count, slotConsumers) => { | ||
| return count + slotConsumers.length; | ||
| }, 0); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment below, but if we're not assigning something directly to these, we should specify the type for each of them (although at that point, then I might prefer the direct assignment).
AFAIU, with a direct assignment at declaration, the static analyzer can infer the type, and thus, also signal when the variable is not used as it should be used. I don't know if it's the same for these without a type. I would imagine that the static analyzer would consider them to have type
any, which would not be helpful to catch errors.Although... since they're declared as "readonly" ... it's possible that the analyzer knows how to infer the type from the assignment in the constructor... I don't really know (google says that that's not the case).
I recognize this is also not introduced here, but that's how it was before, so maybe it's ok to leave it as is, but in the future, let's prefer assignment at declaration.