Skip to content

Commit b16ebba

Browse files
authored
Merge pull request #90 from yoching/fix-multiple-definition
Fix multiple definition fetch issue
2 parents 6b84c5a + 6c6feed commit b16ebba

File tree

10 files changed

+863
-240
lines changed

10 files changed

+863
-240
lines changed

src/Code/Definition/Info.elm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ type alias Info =
2222

2323

2424
makeInfo : Reference -> FQN -> NEL.Nonempty FQN -> Info
25-
makeInfo requestedRef suffixName allFqns =
25+
makeInfo ref suffixName allFqns =
2626
let
2727
( namespace, otherNames ) =
28-
namespaceAndOtherNames requestedRef suffixName allFqns
28+
namespaceAndOtherNames ref suffixName allFqns
2929
in
3030
Info suffixName namespace otherNames
3131

src/Code/Workspace.elm

Lines changed: 108 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ import Code.DefinitionSummaryTooltip as DefinitionSummaryTooltip
1919
import Code.FullyQualifiedName exposing (FQN)
2020
import Code.Hash as Hash
2121
import Code.HashQualified as HQ
22-
import Code.Workspace.WorkspaceItem as WorkspaceItem exposing (Item, WorkspaceItem, WorkspaceItemViewState)
22+
import Code.Workspace.WorkspaceItem as WorkspaceItem exposing (ItemWithReferences, WorkspaceItem, WorkspaceItemViewState)
2323
import Code.Workspace.WorkspaceItems as WorkspaceItems exposing (WorkspaceItems)
2424
import Code.Workspace.WorkspaceMinimap as WorkspaceMinimap
25+
import Dict exposing (Dict)
2526
import Html exposing (Html, article, div, section)
2627
import Html.Attributes exposing (class, id)
2728
import Http
@@ -44,6 +45,7 @@ type alias Model =
4445
, keyboardShortcut : KeyboardShortcut.Model
4546
, workspaceItemViewState : WorkspaceItemViewState
4647
, isMinimapToggled : Bool
48+
, referenceMap : Dict String (List Reference) -- Map of refRequest to list refResponse, to handle multiple-responses case for one request
4749
}
4850

4951

@@ -55,6 +57,7 @@ init config mRef =
5557
, keyboardShortcut = KeyboardShortcut.init config.operatingSystem
5658
, workspaceItemViewState = WorkspaceItem.viewState
5759
, isMinimapToggled = False
60+
, referenceMap = Dict.empty
5861
}
5962
in
6063
case mRef of
@@ -71,7 +74,7 @@ init config mRef =
7174

7275
type Msg
7376
= NoOp
74-
| FetchItemFinished Reference (Result Http.Error Item)
77+
| FetchItemFinished Reference (Result Http.Error (List ItemWithReferences))
7578
| IsDocCropped Reference (Result Dom.Error Bool)
7679
| Keydown KeyboardEvent
7780
| KeyboardShortcutMsg KeyboardShortcut.Msg
@@ -91,62 +94,103 @@ type OutMsg
9194
| ChangePerspectiveToSubNamespace (Maybe Reference) FQN
9295

9396

97+
updateOneItem :
98+
Reference
99+
-> ItemWithReferences
100+
-> ( ( WorkspaceItems, Dict String (List Reference) ), Cmd Msg )
101+
-> ( ( WorkspaceItems, Dict String (List Reference) ), Cmd Msg )
102+
updateOneItem refRequest { item, refResponse } ( ( workspaceItems, referenceMap ), aggCmd ) =
103+
let
104+
refReqeustKey =
105+
Reference.toString refRequest
106+
107+
refResponseList =
108+
referenceMap
109+
|> Dict.get refReqeustKey
110+
|> Maybe.withDefault []
111+
|> (\list -> refResponse :: list)
112+
113+
updatedReferenceMap =
114+
referenceMap
115+
|> Dict.insert refReqeustKey refResponseList
116+
117+
cmd =
118+
-- Docs items are always shown in full and never cropped
119+
if WorkspaceItem.isDocItem item then
120+
Cmd.none
121+
122+
else
123+
isDocCropped refResponse
124+
125+
isDupe wi =
126+
let
127+
ref_ =
128+
WorkspaceItem.reference wi
129+
130+
refEqs =
131+
Reference.equals refResponse ref_
132+
133+
hashEqs =
134+
wi
135+
|> WorkspaceItem.hash
136+
|> Maybe.map (Hash.equals (WorkspaceItem.itemHash item))
137+
|> Maybe.withDefault False
138+
in
139+
(Reference.same refResponse ref_ && not refEqs) || (hashEqs && not refEqs)
140+
141+
-- In some cases (like using the back button between
142+
-- perspectives) we try and fetch the same item twice, not
143+
-- knowing we've fetched it before since one was by hash
144+
-- and the other by name. If found to already be fetched,
145+
-- we favor the newly fetched item and discard the old
146+
deduped =
147+
workspaceItems
148+
|> WorkspaceItems.find isDupe
149+
|> Maybe.map WorkspaceItem.reference
150+
|> Maybe.map (WorkspaceItems.remove workspaceItems)
151+
|> Maybe.withDefault workspaceItems
152+
153+
newWorkspaceItem =
154+
WorkspaceItem.fromItem refResponse item
155+
in
156+
( ( WorkspaceItems.replaceOrPrependWithFocus deduped refResponse newWorkspaceItem
157+
, updatedReferenceMap
158+
)
159+
, Cmd.batch [ aggCmd, cmd ]
160+
)
161+
162+
94163
update : Config -> ViewMode -> Msg -> Model -> ( Model, Cmd Msg, OutMsg )
95-
update config viewMode msg ({ workspaceItems } as model) =
164+
update config viewMode msg ({ workspaceItems, referenceMap } as model) =
96165
case msg of
97166
NoOp ->
98167
( model, Cmd.none, None )
99168

100-
FetchItemFinished ref itemResult ->
169+
FetchItemFinished refRequest itemResult ->
101170
case itemResult of
102171
Err e ->
103-
( { model | workspaceItems = WorkspaceItems.replace workspaceItems ref (WorkspaceItem.Failure ref e) }
172+
( { model | workspaceItems = WorkspaceItems.replace workspaceItems refRequest (WorkspaceItem.Failure refRequest e) }
104173
, Cmd.none
105174
, None
106175
)
107176

108-
Ok i ->
177+
Ok items ->
109178
let
110-
cmd =
111-
-- Docs items are always shown in full and never cropped
112-
if WorkspaceItem.isDocItem i then
113-
Cmd.none
179+
-- remove loading element (with `ref` used for request)
180+
loadingRemoved =
181+
WorkspaceItems.remove workspaceItems refRequest
114182

115-
else
116-
isDocCropped ref
117-
118-
isDupe wi =
119-
let
120-
ref_ =
121-
WorkspaceItem.reference wi
122-
123-
refEqs =
124-
Reference.equals ref ref_
125-
126-
hashEqs =
127-
wi
128-
|> WorkspaceItem.hash
129-
|> Maybe.map (Hash.equals (WorkspaceItem.itemHash i))
130-
|> Maybe.withDefault False
131-
in
132-
(Reference.same ref ref_ && not refEqs) || (hashEqs && not refEqs)
133-
134-
-- In some cases (like using the back button between
135-
-- perspectives) we try and fetch the same item twice, not
136-
-- knowing we've fetched it before since one was by hash
137-
-- and the other by name. If found to already be fetched,
138-
-- we favor the newly fetched item and discard the old
139-
deduped =
140-
workspaceItems
141-
|> WorkspaceItems.find isDupe
142-
|> Maybe.map WorkspaceItem.reference
143-
|> Maybe.map (WorkspaceItems.remove workspaceItems)
144-
|> Maybe.withDefault workspaceItems
145-
146-
nextWorkspaceItems =
147-
WorkspaceItems.replace deduped ref (WorkspaceItem.fromItem ref i)
183+
-- update items with fetched result
184+
( ( nextWorkspaceItems, nextReferenceMap ), cmd ) =
185+
List.foldl (updateOneItem refRequest) ( ( loadingRemoved, referenceMap ), Cmd.none ) items
148186
in
149-
( { model | workspaceItems = nextWorkspaceItems }, cmd, None )
187+
( { model
188+
| workspaceItems = nextWorkspaceItems
189+
, referenceMap = nextReferenceMap
190+
}
191+
, cmd
192+
, None
193+
)
150194

151195
IsDocCropped ref res ->
152196
let
@@ -346,7 +390,7 @@ update config viewMode msg ({ workspaceItems } as model) =
346390

347391

348392
type alias WithWorkspaceItems m =
349-
{ m | workspaceItems : WorkspaceItems }
393+
{ m | workspaceItems : WorkspaceItems, referenceMap : Dict String (List Reference) }
350394

351395

352396
replaceWorkspaceItemReferencesWithHashOnly : Model -> Model
@@ -381,17 +425,24 @@ openReference config model relativeToRef ref =
381425

382426

383427
openItem : Config -> WithWorkspaceItems m -> Maybe Reference -> Reference -> ( WithWorkspaceItems m, Cmd Msg )
384-
openItem config ({ workspaceItems } as model) relativeToRef ref =
428+
openItem config ({ workspaceItems, referenceMap } as model) relativeToRef ref =
385429
-- We don't want to refetch or replace any already open definitions, but we
386430
-- do want to focus and scroll to it (unless its already currently focused)
387-
if WorkspaceItems.member workspaceItems ref then
388-
if not (WorkspaceItems.isFocused workspaceItems ref) then
431+
let
432+
convertedRef =
433+
referenceMap
434+
|> Dict.get (Reference.toString ref)
435+
|> Maybe.andThen List.head
436+
|> Maybe.withDefault ref
437+
in
438+
if WorkspaceItems.member workspaceItems convertedRef then
439+
if not (WorkspaceItems.isFocused workspaceItems convertedRef) then
389440
let
390441
nextWorkspaceItems =
391-
WorkspaceItems.focusOn workspaceItems ref
442+
WorkspaceItems.focusOn workspaceItems convertedRef
392443
in
393444
( { model | workspaceItems = nextWorkspaceItems }
394-
, scrollToDefinition ref
445+
, scrollToDefinition convertedRef
395446
)
396447

397448
else
@@ -400,7 +451,7 @@ openItem config ({ workspaceItems } as model) relativeToRef ref =
400451
else
401452
let
402453
toInsert =
403-
WorkspaceItem.Loading ref
454+
WorkspaceItem.Loading convertedRef
404455

405456
nextWorkspaceItems =
406457
case relativeToRef of
@@ -411,7 +462,10 @@ openItem config ({ workspaceItems } as model) relativeToRef ref =
411462
WorkspaceItems.insertWithFocusBefore workspaceItems r toInsert
412463
in
413464
( { model | workspaceItems = nextWorkspaceItems }
414-
, Cmd.batch [ HttpApi.perform config.api (fetchDefinition config ref), scrollToDefinition ref ]
465+
, Cmd.batch
466+
[ HttpApi.perform config.api (fetchDefinition config convertedRef)
467+
, scrollToDefinition convertedRef
468+
]
415469
)
416470

417471

@@ -531,7 +585,7 @@ handleKeyboardShortcut viewMode model shortcut =
531585
-- EFFECTS
532586

533587

534-
fetchDefinition : Config -> Reference -> ApiRequest Item Msg
588+
fetchDefinition : Config -> Reference -> ApiRequest (List ItemWithReferences) Msg
535589
fetchDefinition config ref =
536590
let
537591
endpoint =
@@ -542,7 +596,7 @@ fetchDefinition config ref =
542596
in
543597
endpoint
544598
|> config.toApiEndpoint
545-
|> HttpApi.toRequest (WorkspaceItem.decodeItem ref) (FetchItemFinished ref)
599+
|> HttpApi.toRequest (WorkspaceItem.decodeList ref) (FetchItemFinished ref)
546600

547601

548602
isDocCropped : Reference -> Cmd Msg

0 commit comments

Comments
 (0)