Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

WIP - Bug 3038 editor search add text search button#3100

Merged
jasonLaster merged 11 commits into
firefox-devtools:masterfrom
ruturajv:bug-3038-editor-search-add-text-search-button
Jun 14, 2017
Merged

WIP - Bug 3038 editor search add text search button#3100
jasonLaster merged 11 commits into
firefox-devtools:masterfrom
ruturajv:bug-3038-editor-search-add-text-search-button

Conversation

@ruturajv

@ruturajv ruturajv commented Jun 6, 2017

Copy link
Copy Markdown
Contributor

Associated Issue: #3038

Even though things are working... the flow gives following errors. Except for the SearchBar.js I'm not sure. Could you guys help me with this?

$ yarn flow
yarn flow v0.24.5
$ flow 
Launching Flow server for /home/rutu/code/debugger.html
Spawned flow server (pid=21157)
Logs will go to /tmp/flow/zShomezSrutuzScodezSdebugger.html.log
SearchBar.js:4
  4: import { findDOMNode } from "../../../node_modules/react-dom/dist/react-dom";
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../../node_modules/react-dom/dist/react-dom. Required module not found

SearchBar.js:8
  8: import Svg from "../shared/Svg";
                     ^^^^^^^^^^^^^^^ ../shared/Svg. Required module not found

SearchBar.js:9
  9: import actions from "../../actions";
                         ^^^^^^^^^^^^^^^ ../../actions. Required module not found

SearchBar.js:18
 18: } from "../../selectors";
            ^^^^^^^^^^^^^^^^^ ../../selectors. Required module not found

SearchBar.js:27
 27: } from "../../utils/editor";
            ^^^^^^^^^^^^^^^^^^^^ ../../utils/editor. Required module not found

SearchBar.js:29
 29: import { scrollList } from "../../utils/result-list";
                                ^^^^^^^^^^^^^^^^^^^^^^^^^ ../../utils/result-list. Required module not found

SearchBar.js:34
 34: import type { SourceRecord } from "../../reducers/sources";
                                       ^^^^^^^^^^^^^^^^^^^^^^^^ ../../reducers/sources. Required module not found

SearchBar.js:35
 35: import type { FileSearchModifiers, SymbolSearchType } from "../../reducers/ui";
                                                                ^^^^^^^^^^^^^^^^^^^ ../../reducers/ui. Required module not found

SearchBar.js:36
 36: import type { SelectSourceOptions } from "../../actions/sources";
                                              ^^^^^^^^^^^^^^^^^^^^^^^ ../../actions/sources. Required module not found

SearchBar.js:37
 37: import type { SearchResults } from ".";
                   ^^^^^^^^^^^^^ Named import from module `.`. This module has no named export called `SearchResults`.

SearchBar.js:40
 40: import _SearchInput from "../shared/SearchInput";
                              ^^^^^^^^^^^^^^^^^^^^^^^ ../shared/SearchInput. Required module not found

SearchBar.js:43
 43: import _ResultList from "../shared/ResultList";
                             ^^^^^^^^^^^^^^^^^^^^^^ ../shared/ResultList. Required module not found

SearchBar.js:46
 46: import type { SymbolDeclaration } from "../../utils/parser/getSymbols";
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../utils/parser/getSymbols. Required module not found

SearchBar.js:93
 93: import "./SearchBar.css";
            ^^^^^^^^^^^^^^^^^ ./SearchBar.css. Required module not found

src/components/Editor/SearchBar.js:307
307:     if (searchType === "text") {
                            ^^^^^^ string literal `text`. This type is incompatible with
298:     { toggle, searchType }: ToggleSymbolSearchOpts = {}
                   ^^^^^^^^^^ string enum

src/components/Editor/SearchBar.js:680
680:               toggleSymbolSearch(e, { toggle: true, searchType });
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ object literal. This type is incompatible with the expected param type of
298:     { toggle, searchType }: ToggleSymbolSearchOpts = {}
                                 ^^^^^^^^^^^^^^^^^^^^^^ object type
  Property `searchType` is incompatible:
    680:               toggleSymbolSearch(e, { toggle: true, searchType });
                                                             ^^^^^^^^^^ string. This type is incompatible with
     83:   searchType: SymbolSearchType
                       ^^^^^^^^^^^^^^^^ string enum

src/components/Editor/SearchBar.js:683
683:             toggleSymbolSearch(e, { toggle: false, searchType });
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ object literal. This type is incompatible with the expected param type of
298:     { toggle, searchType }: ToggleSymbolSearchOpts = {}
                                 ^^^^^^^^^^^^^^^^^^^^^^ object type
  Property `searchType` is incompatible:
    683:             toggleSymbolSearch(e, { toggle: false, searchType });
                                                            ^^^^^^^^^^ string. This type is incompatible with
     83:   searchType: SymbolSearchType
                       ^^^^^^^^^^^^^^^^ string enum


Found 17 errors
error Command failed with exit code 2.

@codehag

codehag commented Jun 6, 2017

Copy link
Copy Markdown
Contributor

Hi Rutrajv! Thanks for helping out! Awesome work!

I ran the project locally with your changes. While I get 3 of the errors that you are showing here, I didn't get any of the import errors. Is there anything else I need to know about your setup?

Regarding the other errors:

Flow types can be a bit tricky if you are just starting out with them. If you aren't familiar with typing, here is the quick version: typing arguments and outputs allows us to know that the inputs and outputs of a given function are correct. This simplifies testing and gives us more certainty in our code. Lets start with a simple error and trace our way back.

src/components/Editor/SearchBar.js:307
307:     if (searchType === "text") {
                            ^^^^^^ string literal `text`. This type is incompatible with
298:     { toggle, searchType }: ToggleSymbolSearchOpts = {}
                   ^^^^^^^^^^ string enum

This is telling us that searchType should be of type string enum (what the heck is that!?), but we are getting "text" instead, which is a string literal. To find out what this all means, its useful to look at the source of this type. We can find this, on line 35 of src/components/Editor/SearchBar.js

import type { FileSearchModifiers, SymbolSearchType } from "../../reducers/ui";

What we can do now is navigate into that file (src/reducers/ui.js) and take a look. There we can find a declaration for SymbolSearchType on line 20. It looks like this:

export type SymbolSearchType = "functions" | "variables";

This flow type is pretty limited. The only acceptable strings for a SymbolSearchType are "functions", and "variables" (or in flow typing is denoted by a single pipe |). It doesn't accept "text"! But we can add it like so:

export type SymbolSearchType = "functions" | "variables" | "text";

The same can go for

298:     { toggle, searchType }: ToggleSymbolSearchOpts = {}
                                 ^^^^^^^^^^^^^^^^^^^^^^ object type

where the default value for ToggleSymbolSearchOpts is an empty object, but both the toggle and searchType are restricted to only accepting certain values. One question might be: do we need the default value? if so, should it be empty? and if yes, we can make the property optional! Let me know if this is the case and I will help you out.

Hopefully this helps! let me know if you have more questions!

codehag
codehag previously requested changes Jun 6, 2017

@codehag codehag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far! A few comments. Since im not too familiar with the issue, but given that we are checking if symbolSearch is disabled for the text search, I think it might make sense to split the logic for the text search and the symbol search.

Comment thread src/components/Editor/SearchBar.js Outdated
function searchTypeBtn(searchType) {
let active =
(symbolSearchOn &&
selectedSymbolType == searchType &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should prefer identity equality === instead of equality == here!

Comment thread src/components/Editor/SearchBar.js Outdated
const { symbolSearchOn, selectedSymbolType } = this.props;

function searchTypeBtn(searchType) {
let active =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this isn't redefined, we should prefer const over let

Comment thread src/components/Editor/SearchBar.js Outdated
(symbolSearchOn &&
selectedSymbolType == searchType &&
searchType !== "text") ||
(!symbolSearchOn && searchType === "text");

@codehag codehag Jun 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a pretty complex boolean. I think it would be more readable if we split this into functions. Maybe something like this:

const { symbolSearchOn, selectedSymbolType } = this.props;

function isSymbolSearchOn(searchType) {
  // since the boolean is so complex, consisting of three parts, lets break it up
  // and use clear variable names to make it obvious what is happening
  const isSymbolSearch = selectedSymbolType === searchType;
  const notSearchText = searchType !== "text";

  return (symbolSearchOn && isSearchType && notSearchText);
}

function isSearchText(searchType) {
  return (!symbolSearchOn && searchType === "text");
}

function isTextSearch(searchType) {
  const { symbolSearchOn } = this.props;
  return (symbolSearchOn && searchType === "text");
}

const active = isSymbolSearchOn() || isSearchText()

But, this still looks rather complex to me. So I suspect something might need to change about our approach here ...

This is a "if you have time" suggestion, as we can definitely do the simpler version.

From reading the code, we can see that SymbolSearch and SearchText are two different things that are at odds with eachother. You mentioned elsewhere that you have problems with the flow typing. SymbolSearchType doesn't have a "text" as an available input.

Since you are explicitly checking if SymbolSearchOn is off when it is of type text -- we probably do not want to change that flow type to accept that as a valid type. It doesnt make sense for "text" to be a valid SymbolSearchType if symbolSearchOn is false.

Maybe we need a new function (it might even share a lot of the code), which is "searchTextBtn" with a new variable that has its own flow type? You can copy the SymbolSearchType and make a TextSearchType with just "text" as a valid value. That might simplify the code!

This solution will take longer though, and will require some renaming. Let me know what you think and if you need help.

@ruturajv

ruturajv commented Jun 6, 2017

Copy link
Copy Markdown
Contributor Author

Hey @codehag

Thanks a lot for your help, yes I'm new to flow.

Regarding the simplification of active - Yes I too think its too complicated right now.

Let me work on your suggestions.

@codecov

codecov Bot commented Jun 7, 2017

Copy link
Copy Markdown

Codecov Report

Merging #3100 into master will increase coverage by 0.11%.
The diff coverage is 44.11%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3100      +/-   ##
==========================================
+ Coverage   47.43%   47.54%   +0.11%     
==========================================
  Files          97       97              
  Lines        4018     4036      +18     
  Branches      826      828       +2     
==========================================
+ Hits         1906     1919      +13     
- Misses       2112     2117       +5
Impacted Files Coverage Δ
src/components/Editor/SearchBar.js 24.77% <44.11%> (+2.72%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 11757c9...9ebddfe. Read the comment docs.

@ruturajv

ruturajv commented Jun 7, 2017

Copy link
Copy Markdown
Contributor Author

Hey @codehag

I've fixed some of the errors by not checking for text string.

The searchTypeBtn was initially just generating buttons for symobolSearch related filters, now the button is also generating a non-symbolSearch filter ie - text.

Hence the toggleSymbolSearch either needs to drop type checks of ToggleSymbolSearchOpts or we need to split the toggleSymbolSearch - what would you suggest ?

@codehag

codehag commented Jun 7, 2017

Copy link
Copy Markdown
Contributor

Hi Ruturajv! Nice work, its starting to look cleaner.

I think that your impulse with checking for "text" as a type was a good one actually. Also, I agree that searchBtn was originally intended for SymbolSearches. I think the changes you made are good in that they are cleaner, but they also hide that there is a third potential value for searchType, which is "text". It would be better to introduce a new flow type, rather than removing an existing one. How about this as a solution: Lets expand the definition of searchType like so:

// lines 81-84

type TextSearchType = "text";

type ToggleSymbolSearchOpts = {
  toggle: boolean,
  searchType: SymbolSearchType | TextSearchType
};

then we can do the check for if (searchType === "text") .. as you had it before, and this will be clearer and easier to understand for the next person who reads the code.

Further, with your case statement, we can do the same, adding a case for "text".

Comment thread src/components/Editor/SearchBar.js Outdated

// Check if searchType is "text"
if (!["functions", "variables"].includes(searchType)) {
this.props.toggleSymbolSearch(false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, this seems a bit out of date given what we're doing now. Maybe we want it to be: setEditorSearchType and that can include text

@ruturajv

ruturajv commented Jun 9, 2017

Copy link
Copy Markdown
Contributor Author

@jasonLaster hmm.. yaa seems lot might change here... even after @codehag suggestions, these errors persist

$ yarn flow
yarn flow v0.24.5
$ flow 
src/components/Editor/SearchBar.js:326
326:         this.props.setSelectedSymbolType(searchType);
                                              ^^^^^^^^^^ string literal `text`. This type is incompatible with the expected param type of
115:     setSelectedSymbolType: SymbolSearchType => any,
                                ^^^^^^^^^^^^^^^^ string enum

src/components/Editor/SearchBar.js:334
334:       this.props.setSelectedSymbolType(searchType);
                                            ^^^^^^^^^^ string literal `text`. This type is incompatible with the expected param type of
115:     setSelectedSymbolType: SymbolSearchType => any,
                                ^^^^^^^^^^^^^^^^ string enum

@codehag codehag force-pushed the bug-3038-editor-search-add-text-search-button branch from b72889a to 0e41604 Compare June 12, 2017 16:06
@codehag codehag force-pushed the bug-3038-editor-search-add-text-search-button branch from 0e41604 to 6433397 Compare June 12, 2017 16:11
@codehag codehag dismissed their stale review June 12, 2017 16:11

made some fixes

@codehag

codehag commented Jun 12, 2017

Copy link
Copy Markdown
Contributor

Hi @ruturajv! Thanks again for doing this. I went in and I wrestled with the code a bit, since upon working with it I realized it needed a refactor. Here is what I did:

  • split the road: searching for text and searching for symbols are two different logical operations. One of the things that made toggleSymbolSearch so dang confusing was it was doing too many jobs.

  • remove extra if statements. We had a bunch of if statements in there that didn't make any sense. By splitting the logic, both functions are much easier to read and reason about.

  • sticking to the defined type. We don't always want to stick to a type, but sometimes it tells us how code is intended to be used. The type we were working with was a Symbol. By respecting that type, I realized that -- hey, that should stay as it is! we want to do something else here.

If anything is confusing, ping me! I am more than happy to explain further :)

@ruturajv

Copy link
Copy Markdown
Contributor Author

@codehag Thanks for the huge rewrite :)

Let me pull and go through it.

@codehag codehag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made some comments about stuff i missed too, ill probably get to them later today


function searchTypeBtn(searchType) {
const active = isButtonActive(searchType);
const toggle = selectedSymbolType == searchType;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be identity equality ===

Comment thread src/components/Editor/index.js Outdated
const getExpressionSel = createSelector(expressionsSel, expressions => input =>
expressions.find(exp => exp.input == input)
);
expressions.find(exp => exp.input == input));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be identity equality ===

let bar = 2;
const baz = 3;
const a = 4,
b = 5;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style nit: this should be

const a = ...;
const b = ...;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this actually should be this way becase we're testing the weird behavior :) We want to make sure we find those vars too :P

@ruturajv did this i believe

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ohhh i understand

Ruturaj K. Vartak added 2 commits June 14, 2017 10:37

@jasonLaster jasonLaster left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💃

@jasonLaster jasonLaster merged commit 40df77e into firefox-devtools:master Jun 14, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants