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
Fix part of #7176: Remove any from RuleObjectFactory and introduce TypeChangeService #9365
Changes from 2 commits
b8fbdb5
614be0f
1f87d72
ab69594
1a806fd
40e0f3a
471fa5d
3e9f9e7
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 |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Copyright 2020 The Oppia 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. | ||
|
||
/** | ||
* @fileoverview Factory to determine correct type of RuleInputs | ||
*/ | ||
|
||
import { downgradeInjectable } from '@angular/upgrade/static'; | ||
import { Injectable } from '@angular/core'; | ||
|
||
import { IRuleInput } from 'domain/exploration/RuleObjectFactory'; | ||
import { INumberWithUnitsBackendDict } from | ||
'domain/objects/NumberWithUnitsObjectFactory'; | ||
import { IFractionDict } from | ||
'domain/objects/FractionObjectFactory.ts'; | ||
/* eslint-disable max-len */ | ||
import { INote } from 'extensions/interactions/MusicNotesInput/directives/music-notes-input-rules.service'; | ||
/* eslint-enable max-len */ | ||
import { IGraphBackendDict } from | ||
'extensions/interactions/GraphInput/directives/graph-detail.service'; | ||
|
||
@Injectable({ | ||
providedIn: 'root' | ||
}) | ||
export class RuleInputTypeFactory { | ||
_isGraph(variable: Object): variable is IGraphBackendDict { | ||
if (this._isString(variable) || this._isNumber(variable)) { | ||
return false; | ||
} | ||
|
||
return 'vertices' in variable; | ||
} | ||
|
||
_isNoteArray(variable: Object): variable is INote[] { | ||
if (Array.isArray(variable)) { | ||
if (variable.length === 0) { | ||
return true; | ||
} | ||
|
||
if (typeof variable[0] === 'string' || typeof variable[0] === 'number') { | ||
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. There are other datatypes as well, right? That can come here. Also, do the same check for all variables in the array, currently it is done only on the first element? 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. @aks681 Actually we don't have to check everything completely because we know 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. Ditto - add comments. 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. @nishantwrp As @ankita240796 said, add comments for all these. But, are we validating anywhere that |
||
return false; | ||
} | ||
|
||
return 'readableNoteName' in variable[0]; | ||
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. Similar comment, the field may be there in variable[0] but may not be in other elements, so make sure to check all elements. 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. Same reply as above. |
||
} | ||
|
||
return false; | ||
} | ||
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. Now, in these functions we had two options
Currently I've followed the second point. Which one do you guys prefer? 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. 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'm not sure what is the difference here, in one case we would be using just 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. The first point means something like this _isNoteArray(variable: Object): variable is INote[] {
return true;
} 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 that the second option is fine, thanks! 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. Also, I was thinking we could have a general 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'm fine with using the first appraoch if you're not able to do it with the second. 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.
So, are we planning to fix this later or is there any other issue with fixing this? 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 I think it doesn't need to be fixed. It's something like suppose inputs.x.vertices = [2,2]; It will throw a ts error that Now if we use our But with the first method, we can just assume that it is of type 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. Ok, thanks for explaining. |
||
|
||
_isNumberWithUnits( | ||
variable: Object): variable is INumberWithUnitsBackendDict { | ||
if (this._isString(variable) || this._isNumber(variable)) { | ||
return false; | ||
} | ||
|
||
return 'fraction' in variable; | ||
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. Ditto about checking all fields here and elsewhere. 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. Same reply as above. We don't have to check everything. Moreover is it sure that in the entire codebase the 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. You can add a high level comment to explain this logic -- if not with every type check. Or it would be a better idea to add some documentation around this on wiki as well just to avoid confusion. |
||
} | ||
|
||
_isFraction(variable: Object): variable is IFractionDict { | ||
if (this._isString(variable) || this._isNumber(variable)) { | ||
return false; | ||
} | ||
|
||
return 'numerator' in variable; | ||
} | ||
|
||
_isString(variable: Object): variable is string { | ||
return typeof variable === 'string'; | ||
} | ||
|
||
_isNumber(variable: Object): variable is number { | ||
return typeof variable === 'number'; | ||
} | ||
|
||
_isStringArray(variable: Object): variable is string[] { | ||
return (Array.isArray(variable) && ( | ||
variable.length === 0 || typeof variable[0] === 'string')); | ||
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. Ditto here about only checking first element. 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. Same reply as above. |
||
} | ||
|
||
_isStringArrayArray(variable: Object): variable is string[][] { | ||
return (Array.isArray(variable) && ( | ||
variable.length === 0 || (Array.isArray(variable[0]) && ( | ||
variable[0].length === 0 || typeof variable[0][0] === 'string')))); | ||
} | ||
|
||
_isNumberArray(variable: Object): variable is number[] { | ||
return (Array.isArray(variable) && ( | ||
variable.length === 0 || typeof variable[0] === 'number')); | ||
} | ||
|
||
graphInstance(variable: IRuleInput): IGraphBackendDict { | ||
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. Maybe rename to smtg like Also, what happens if it is not an instance, shouldn't there be a return null or maybe throw Error? and why is the same variable that is passed in, returned? Can't the calling function just use that variable if the check passes? This could just be an Ditto below 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.
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. Ah ok, so you are basically type casting the variable from an IRuleInput to IGraphBackendDIct for ts compiler. Is that it? Add that in a comment for this function. 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. done! |
||
if (this._isGraph(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
notesInstance(variable: IRuleInput): INote[] { | ||
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. Ditto about adding comment. |
||
if (this._isNoteArray(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
numberWithUnitsInstance(variable: IRuleInput): INumberWithUnitsBackendDict { | ||
if (this._isNumberWithUnits(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
fractionInstance(variable: IRuleInput): IFractionDict { | ||
if (this._isFraction(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
stringInstance(variable: IRuleInput): string { | ||
if (this._isString(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
numberInstance(variable: IRuleInput): number { | ||
if (this._isNumber(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
stringArrayInstance(variable: IRuleInput): string[] { | ||
if (this._isStringArray(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
stringArrayArrayInstance(variable: IRuleInput): string[][] { | ||
if (this._isStringArrayArray(variable)) { | ||
return variable; | ||
} | ||
} | ||
|
||
numberArrayInstance(variable: IRuleInput): number[] { | ||
if (this._isNumberArray(variable)) { | ||
return variable; | ||
} | ||
} | ||
} | ||
|
||
angular.module('oppia').factory('RuleInputTypeFactory', | ||
downgradeInjectable(RuleInputTypeFactory)); |
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.
Could you please explain how
variable is IGraphBackendDict
works?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.
It tells the ts compiler that the
variable
is of typeIGraphBackendDict
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.
Hmm, but how is it different from
variable: IGraphBackendDict
?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.
Case 1
It means that func1 returns a object whose type is GraphDict
Case 2
It means that func1 returns a
boolean
and if thatstrue
it means a is of type GraphDictThere 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.
Ok, thanks
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.
I would suggest to add comments for all this. In general, wherever you think a reviewer might have a question, add comments in advance.