Ignore "Variable might have not been defined" in specific place - phpstorm

I have code like this
<?php
$first_condition = time() % 2 == 0;
$second_condition = time() % 3 == 0;
if ($first_condition) {
if ($second_condition) {
$param1 = 'param1_1_1';
} else {
$param1 = 'param1_2_1';
$param2 = 'param2_2_1';
}
} else {
if ($second_condition) {
$param1 = 'param1_1_2';
} else {
$param1 = 'param1_2_2';
$param2 = 'param2_2_2';
}
}
if ($second_condition) {
$param2 = $param1;
}
$total = array(
'param1' => $param2,
'param2' => $param1,
);
I really know that $param2 would be defined anyway, but PhpStorm say that it's wrong.
Is exist there any way to mark this place as ignored of this inspection? Only this place, not global settings, and only this inspection, not all.

Sure -- you can suppress such warning for that statement.
Standard procedure:
Place caret on such error/warning.
Invoke Alt + Enter to bring quick fix menu (or via light bulb icon).
Find the right inspection.
Expand submenu (e.g. Arrow Right using keyboard or using mouse -- note: click area can be quite small -- depends on GUI theme used).
Choose Suppress for statement option.
The above will add special PHPDoc-like comment (/** #noinspection PhpUndefinedVariableInspection */) just before that statement -- it tells IDE to ignore that particular issue here.
https://www.jetbrains.com/help/phpstorm/suppressing-inspections.html?search=suppress
On another hand (especially if it's your code/code that you cane edit): why not go a bit safer route and just declare those $paramX variables with default values (e.g. empty string) before the conditionals ... so the variable will be indeed defined? This will prevent such false complains from IDE (when it tries to statically analyse such rather complex logic).
New subquestion: is it possible to disable inspection only for param1 but not for param2 using /** #noinspection PhpUndefinedVariableInspection */ ?
Yes and No.
Without making changes to the code -- No. Those variables are both used in one statement (array definition) and suppression comment is applied to the whole statement.
Yes -- split it into 2 statements if you need such separate suppression.

Related

Increasing Value of State Variable in ForEach loop for Progress Bar in React

I'm trying to figure out a way to build a progress bar with React. I have a forEach loop that iterates through an array of about 7,000 indexes. Each time I validate a row, I want to update a state variable with percentage completion (and render this on the page live). I've tried iterating through these indexes, and updating my state variable (hoping to update the page) in the loop but I'm realizing that will not work. I obviously can't do this with a normal variable as it will reset when the component re-renders. Can anyone give me some insight on this topic?
Thanks.
Here is a code snippet from what I'm looking at:
parsedAssets.forEach(asset => {
newAssetValidated = validateBulkUpload(asset, parsedAssets, assetList, accountLogged, jobSites);
!newAssetValidated.reject_err ? validatedAssetList.accepted.push(newAssetValidated) : validatedAssetList.rejected.push(newAssetValidated);
setStateAssets({ ...stateAssets, validatedAssetList });
});
}
So essentially, as each asset is either accepted or rejected we add it to "stateAssets", and I'm hoping to build the progress bar from the length of the combined arrays that are getting set in stateAssets. However, when the forEach loop is completed, only the last validated asset is getting set due to it not updating until the forEach loop is completed.
Personally I can't imagine such a heavy validation, that you need progress-bar, but anyway.
First solution is to separate validation itself from state update for progress-bar into separate "threads". But since JS is single threaded, you may use some tricks with setTimeout or setInterval functionality. It may be very tricky, and in general not recommended practice with React.
Another way is - to set the work into queue & process 1 item at a time.
As an example I would do it something like this:
function ComponentWithProgress({parsedAssets, setParsedAssets}) {
const [validatedAssetList, setValidatedAssetList] = useState([])
const [progress, setProgress] = useState(0)
const [toDo, setToDo] = useState([])
if(parsedAssets && parsedAssets.length>0) {
setToDo(parsedAssets)
// clear parsedAssets in parent component to: [], false, null ...
// so you put it into toDo only once
setParsedAssets([])
}
if(toDo.length > 0) {
const asset = toDo[0]
const newToDo = toDo.slice(1) // All but 0th element
const newAssetValidated = validateBulkUpload(asset);
setValidatedAssetList([ ...validatedAssetList, newAssetValidated ]);
setToDo(newToDo)
setProgress( newToDo.length / ( validatedAssetList.length + newToDo.length ) * 100 )
}
// ... Render here
// If you need only accepted
const accepted = validatedAssetList.filter(v => !v.reject_err)
}
This example maybe not work for you as is, because you didn't showed us the context, but the main idea is here.

Can I include conditional logic in VS Code snippets?

I would like to write a snippet in VS Code that writes a "switch" expression (in Javascript), but one where I can define the number of cases.
Currently there is a snippet that produces the outline of a switch expression with 1 case, and allows you to tab into the condition, case name, and the code contained within.
I want to be able to type "switch5" ("5" being any number) and a switch with 5 cases to be created, where I can tab through the relevant code within.
I know the snippets are written in a JSON file, can I include such conditional logic in this, or is it not possible?
Thanks!
The short answer is that you cannot do that kind of thing in a standard vscode snippet because it cannot dynamically evaluate any input outside of its designated variables with some limited workarounds like I'll mention next.
You might - I and others have written answers on SO about his - type your various case values first and then trigger a snippet tat would transform them into a switch statement. It is sort of doing it backwords but it might be possible.
There are extensions, however, that do allow you to evaluate javascript right in a snippet or setting and output the result. macro-commander is one such extension. I'll show another simpler extension doing what you want: HyperSnips.
In your javascript.hsnips:
snippet `switch(\d)` "add number of cases to a switch statement" A
``
let numCases = Number(m[1]) // 'm' is an array of regex capture groups
let caseString = ''
if (numCases) { // if not 'switch0'
let tabStopNum = 1
caseString = `switch (\${${tabStopNum++}:key}) {\n`
for (let index = 0; index < m[1]; index++) {
caseString += `\tcase \${${tabStopNum++}:value}:\n\t\t\$${tabStopNum++}\n`
caseString += '\t\tbreak;\n\n'
}
caseString += '\tdefault:\n'
caseString += '\t\tbreak;\n}\n'
}
rv = `${caseString}` // return value
``
endsnippet
The trickiest part was getting the unknown number of tabstops to work correctly. This is how I did it:
\${${tabStopNum++}:key}
which will resolve to ${n:defaultValue} where n gets incremented every time a tabstop is inserted. And :defaultValue is an optional default value to that tabstop. If you don't need a defaultValue just use \$${tabStopNum++} there.
See https://stackoverflow.com/a/62562886/836330 for more info on how to set up HyperSnips.

How to use a signal as function parameter in CAPL

I am trying to write a function in CAPL that takes a signal and calculates the physical value with the signal value, the signal factor and the signal offset.
This is how a simple gateway normally works:
message CAN1.myMessage1 myMessage1 = {DIR = RX};//message from the database
message CAN2.myMessage2 myMessage2 = {DIR = TX};//another message from the database
on message CAN1.*
{
if(this.id == myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = myMessage1.mySignalA * myMessage1.mySignalA.factor + myMessage1.mySignalA.offset;
}
}
And this is what I am trying to do:
...
on message CAN1.*
{
if(this.id ==myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = PhysicalValue(myMessage1.mySignalA);
}
}
double PhysicalValue(signal * s)
{
return s*s.factor+s.offset;
}
There are two problems with this code:
Firstly when I pass the signal as the parameter the compiler says that the types don't match. The second problem is that inside the function the attributes (factor and offset) are no longer recognized.
These problems might have something to do with the weird object-oriented-but-not-really nature of CAPL. The value of the signals can be accessed directly but it also has attributes?
int rawValue = myMessage1.mySignalA;
If you are familiar with C you might say that the problem is that I am specifying a pointer in the function but that I am not passing a pointer into it. But in CAPL there are no pointers and the * simply means anything.
Without the * I would have needed to use a specific signal which would have defeated the purpose of the function.
EDIT:
I have found the attribute .phys by now which does exactly what my demo function would have done.
double physValue = myMessage1.mySignalA.phys;
This has already made my code much shorter but there are other operations that I need to perform for multiple signals so being able to use signals as a function parameter would still be useful.
What you can do is this:
double PhysicalValue(signal * s)
{
// access signal by prepending a $
return $s.phys;
}
Call like this
on message CAN1.*
{
if(this.id ==myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = PhysicalValue(CAN1::myMessage1::mySignalA);
}
}
I.e. when you call your function, you have to provide the qualified name of the signal (with colons rather than dots). To my knowledge it is not possible to use myMessage1.mySignalA, since signals itself are not a CAPL datatype.
Apart from this, you might re-think whether you really should be using on message, but rather switch to on signal. Handling the signal values no matter with which message they are sent is done by CANoe's signal server.
Note that CANoe already has a function which does exactly what you're trying to do (multiplying by factor and adding offset). It's called getSignal:
on message CAN1.*
{
if(this.id == myMessage1.id)
{
myMessage2.mySignalB = getSignal(myMessage1::mySignalA);
}
}
Offsets and factors are defined in e.g. the DBC files.

LINQ-to-SQL oddity with multiple where clause arguments on the same field

My problem requires me to dynamically add where clauses to a IQueryable based on user input. The problem i'm having is that Linq-to-SQL doesn't seem to like having multiple where clauses on the same field, it actually duplicates the search arg value for the last item on all parameters. I verified this behavior through a SQL trace. Here is what I'm seeing.
WHERE ([t22].[OpenText] LIKE #p11) AND ([t22].[OpenText] LIKE #p12)
-- #p11: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%] // Should be 2da57652-dcdf-4cc8-99db-436c15e5ef50
-- #p12: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%]
My code uses a loop to dynamically add the where clauses as you can see below. My question is how do I work around this? This pretty much seems like a bug with the tool, no?
// add dyanmic where clauses based on user input.
MatchCollection searchTokens = Helper.ExtractTokensWithinBracePairs(filterText);
if (searchTokens.Count > 0)
{
foreach(Match searchToken in searchTokens)
query = query.Where((material => material.OpenText.Contains(searchToken.Value)));
}
else
{
query = query.Where((material => material.OpenText.Contains(filterText)));
}
Closing over the loop variable considered harmful! Change
foreach(Match searchToken in searchTokens) {
query = query.Where(
material => material.OpenText.Contains(searchToken.Value)
);
}
to
foreach(Match searchToken in searchTokens) {
Match token = searchToken;
query = query.Where(
material => material.OpenText.Contains(token.Value)
);
}
You are closing over the loop variable, which is considered harmful. To fix do this:
foreach(Match searchToken in searchTokens)
{
Match searchToken2 = searchToken;
// ^^^^^^^^^^^^ copy the value of the reference to a local variable.
query = query.Where(material => material.OpenText.Contains(searchToken2.Value));
// use the copy here ^^^^^^^^^^^^
}
The reason why your version doesn't work is that the query refers to the variable searchToken, not the value it had when the query was created. When the variable's value changes, all your queries see the new value.
I don't have enough rep to leave comments yet (or this would be a comment and not an answer) but the answers listed here worked for me.
However, I had to turn off compiler optimizations in order for it to work. If you do not turn off compiler optimizations (at least at the method level) then the compiler sees you setting a loop variable to a local variable and throws the local variable away.

Most readable way to write simple conditional check

What would be the most readable/best way to write a multiple conditional check such as shown below?
Two possibilities that I could think of (this is Java but the language really doesn't matter here):
Option 1:
boolean c1 = passwordField.getPassword().length > 0;
boolean c2 = !stationIDTextField.getText().trim().isEmpty();
boolean c3 = !userNameTextField.getText().trim().isEmpty();
if (c1 && c2 && c3) {
okButton.setEnabled(true);
}
Option 2:
if (passwordField.getPassword().length > 0 &&
!stationIDTextField.getText().trim().isEmpty() &&
!userNameTextField.getText().trim().isEmpty() {
okButton.setEnabled(true);
}
What I don't like about option 2 is that the line wraps and then indentation becomes a pain. What I don't like about option 1 is that it creates variables for nothing and requires looking at two places.
So what do you think? Any other options?
if (HasPassword() && HasStation() && HasUserName())
okButton.setEnabled(true);
bool HasPassword() {
return passwordField.getPassword().length > 0;
}
etc.
Note that option 1 does not allow for short circuiting behavior. That is, you calculate the value of all of the conditionals before evaluating the result of the first.
I would modify option 1 so that you're using variable names that actually have a meaning. That is, change the name of "c2" to be something like "stationIDIsEmpty" (and move the NOT into the conditional). That way the conditional is readable without having to glance back and forth for every variable.
So my code would probably look like:
boolean enteredPassword = passwordField.getPassword().length > 0;
boolean stationIDIsEmpty = stationIDTextField.getText().trim().isEmpty();
boolean userNameIsEmpty = userNameTextField.getText().trim().isEmpty();
if (enteredPassword && !stationIDIsEmpty && !userNameIsEmpty) {
okButton.setEnabled(true);
}
I voted for Chris Brandsma's answer.
But just wanted to mention the main issue I have with Option 1 is you are losing the benefit of &&. With option one, although I think it's more readable, you are processing comparisons when they may not be required.
Personally, I like the second way, because I find that using that way can make the predication of the conditionals clear. That is, with that method done properly, you can make the conditional comprehensible by "verablizing" it (whether or not you actually speak it is irrelevant).
That is, with your second option, it becomes clear that your conditional translates roughly as this: "If the password length is greater than zero, AND the stationIDTextField (trimmed) is NOT empty, AND the usernameTextField (trimmed) is NOT empty, then..."
I prefer the following:
if (passwordField.getPassword().length > 0
&& ! stationIDTextField.getText().trim().isEmpty()
&& ! userNameTextField.getText().trim().isEmpty())
{
okButton.setEnabled(true);
}
With this coding style I accomplish two things:
I can easily see that each extra line of the if is part of the condition because of the && (or ||) at the beggining.
I can easily see where the if statement ends because of the { at the next line.
Option1 is prime for applying the refactoring 'Replace temp with Query'. The reason being that someone can stuff in code between the variable is initialized and the check and change the behavior of the code. Or the check might be made with stale values.. an update has been made to the textfields between initialization and checking.
So my attempt at this would be
if (GetPasswordLength() > 0
&& FieldHelper.IsNotEmpty(stationIDTextField)
&& FieldHelper.IsNotEmpty(userNameTextField)
{
okButton.setEnabled(true);
}
FieldHelper is a class with public static methods (also called a Utility class / Static class in C#)