Fix a set of issues in Component Browser (#8377)

Part of #8372

* Sorting was broken (sort's argument was removed)
* searching by initials now does not skip words
* icons: now we use same logic as existing nodes.
* local entities has worse score if "showLocals" option is toggled off.

# Important Notes
Please be aware that there is still an important issue with groups; sometimes they're not loaded. Reported [here](8376)
This commit is contained in:
Adam Obuchowicz 2023-11-23 16:53:59 +01:00 committed by GitHub
parent 4b3ba78b52
commit ce584862ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 22 deletions

View File

@ -6,6 +6,7 @@ import {
type SuggestionId,
} from '@/stores/suggestionDatabase/entry'
import { compareOpt } from '@/util/compare'
import { displayedIconOf } from '@/util/getIconName'
import type { Icon } from '@/util/iconName'
import { isSome } from '@/util/opt'
import { qnIsTopElement, qnLastSegmentIndex } from '@/util/qualifiedName'
@ -100,7 +101,7 @@ export function makeComponent(
return {
...labelOfEntry(entry, filtering, match),
suggestionId: id,
icon: entry.iconName ?? 'marketplace',
icon: displayedIconOf(entry),
group: entry.groupIndex,
}
}
@ -114,6 +115,6 @@ export function makeComponentList(db: SuggestionDb, filtering: Filtering): Compo
}
}
}
const matched = Array.from(matchSuggestions()).sort()
const matched = Array.from(matchSuggestions()).sort(compareSuggestions)
return Array.from(matched, (info) => makeComponent(info, filtering))
}

View File

@ -62,7 +62,8 @@ class FilteringWithPattern {
'i',
)
if (pattern.length > 1 && !/_/.test(pattern)) {
// Similar to `wordMatchRegex`, but each letter in the pattern is considered a word.
// Similar to `wordMatchRegex`, but each letter in the pattern is considered a word,
// and we don't skip word (initials must match consecutive words).
// The first match (`match[1]`) is the part before the first matched letter.
// The rest of the matches come in groups of two:
// - The matched letter
@ -70,7 +71,7 @@ class FilteringWithPattern {
const regex = pattern
.split('')
.map((c) => `(${c})`)
.join('(.*?_)')
.join('([^_]*?_)')
this.initialsMatchRegex = new RegExp('(^|.*?_)' + regex + '(.*)', 'i')
}
}
@ -338,21 +339,22 @@ export class Filtering {
else return { score: 0 }
}
private isLocal(entry: SuggestionEntry): boolean {
return this.currentModule != null && entry.definedIn === this.currentModule
}
filter(entry: SuggestionEntry): MatchResult | null {
let qualifiedNameMatch: Opt<MatchedParts>
if (entry.isPrivate) return null
else if (!this.selfTypeMatches(entry)) return null
else if (!(qualifiedNameMatch = this.qualifiedNameMatches(entry))) return null
else if (!this.showUnstable && entry.isUnstable) return null
else if (
this.showLocal &&
(this.currentModule == null || entry.definedIn !== this.currentModule)
)
return null
else if (this.showLocal && !this.isLocal(entry)) return null
else if (this.pattern) {
const patternMatch = this.pattern.tryMatch(entry)
if (!patternMatch || !qualifiedNameMatch) return patternMatch
else return { ...qualifiedNameMatch, ...patternMatch }
if (!patternMatch) return null
if (!this.showLocal && this.isLocal(entry)) patternMatch.score *= 2
return { ...qualifiedNameMatch, ...patternMatch }
} else if (this.isMainView()) return this.mainViewFilter(entry)
else return { score: 0 }
}

View File

@ -8,7 +8,7 @@ import { injectGraphSelection } from '@/providers/graphSelection'
import { useGraphStore, type Node } from '@/stores/graph'
import { useApproach } from '@/util/animation'
import { usePointer, useResizeObserver } from '@/util/events'
import { mapOldIconName, typeNameToIcon } from '@/util/getIconName'
import { displayedIconOf, mapOldIconName, typeNameToIcon } from '@/util/getIconName'
import type { Opt } from '@/util/opt'
import { Rect } from '@/util/rect'
import { Vec2 } from '@/util/vec2'
@ -123,16 +123,12 @@ const executionState = computed(() => expressionInfo.value?.payload.type ?? 'Unk
const suggestionEntry = computed(() => graph.db.nodeMainSuggestion.lookup(nodeId.value))
const color = computed(() => graph.db.getNodeColorStyle(nodeId.value))
const icon = computed(() => {
if (suggestionEntry.value?.iconName) {
return mapOldIconName(suggestionEntry.value.iconName)
}
const methodName = expressionInfo.value?.methodCall?.methodPointer.name
if (methodName == null && outputTypeName.value != null) {
return typeNameToIcon(outputTypeName.value)
} else {
return 'enso_logo'
}
const expressionInfo = graph.db.getExpressionInfo(nodeId.value)
return displayedIconOf(
suggestionEntry.value,
expressionInfo?.methodCall?.methodPointer,
outputTypeName.value,
)
})
const nodeEditHandler = nodeEditBindings.handler({

View File

@ -1,4 +1,6 @@
import type { SuggestionEntry, Typename } from '@/stores/suggestionDatabase/entry'
import type { Icon } from '@/util/iconName'
import type { MethodPointer } from 'shared/languageServerTypes'
const oldIconNameToNewIconNameLookup: Record<string, string> = {
/* eslint-disable camelcase */
@ -35,3 +37,13 @@ const typeNameToIconLookup: Record<string, Icon> = {
export function typeNameToIcon(typeName: string): Icon {
return typeNameToIconLookup[typeName] ?? 'enso_logo'
}
export function displayedIconOf(
entry?: SuggestionEntry,
methodCall?: MethodPointer,
actualType?: Typename,
): Icon {
if (entry?.iconName) return mapOldIconName(entry.iconName)
if (!methodCall?.name && actualType) return typeNameToIcon(actualType)
return 'enso_logo'
}