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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Limit definition search to provided relativeTo #3194
Conversation
@@ -274,7 +274,7 @@ suffixedTermName :: Int -> Referent -> NamesWithHistory -> [HQ'.HashQualified Na | |||
isHQ'd = R.manyDom fqn rel -- it is conflicted | |||
hq n = HQ'.take length (hq' n r) | |||
hqn = if isHQ'd then hq n' else HQ'.fromName n' | |||
in (isHQ'd, Name.countSegments fqn, Name.isAbsolute n', hqn) | |||
in (isHQ'd, Name.countSegments n', Name.isAbsolute n', hqn) |
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.
Prefer shortest name by the abbreviated name, rather than the fully qualified name.
@@ -322,13 +322,11 @@ findShallowReadmeInBranchAndRender :: | |||
Width -> | |||
Rt.Runtime Symbol -> | |||
Codebase IO Symbol Ann -> | |||
NamesWithHistory -> | |||
PPE.PrettyPrintEnvDecl -> |
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.
This function only uses a PPE
else do | ||
flip prettyAndParseNamesForBranch (AllNames path) <$> resolveCausalHash (Just bh) codebase | ||
|
||
let localPPE = PPE.fromNamesDecl hashLen (NamesWithHistory.fromCurrentNames localNames) |
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.
Use the trick from #3172 to improve names chosen in PPE
e57861f
to
c8a0ab2
Compare
termNames <- Q.rootTermNames | ||
typeNames <- Q.rootTypeNames | ||
pure (fmap (bimap s2cTextReferent (fmap s2cConstructorType)) <$> termNames, fmap s2cTextReference <$> typeNames) | ||
rootNamesByPath :: |
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.
Now that I have the namespace in sqlite it's easy to partition names in sqlite which is likely faster than doing it in Haskell.
PPE.fromNamesDecl hqLength (NamesWithHistory.fromCurrentNames printNames) | ||
|
||
width = | ||
(_parseNames, _printNames, localNamesOnly, ppe) <- scopedNamesForBranchHash codebase root path |
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.
The biggest change in this function is that we previously used "prettyNames" for our initial term search which would erroneously fall-back to global names even though we're explicitly searching within a namespace.
Now any searches for scope-local things use localNamesOnly
explicitly, and in cases where fallback is desired we use a smart PPE which does suffixification and fall-back correctly.
unison-core/src/Unison/Names.hs
Outdated
-- E.g. | ||
-- ["base.List.map", "base.Bag.map"] -> ["List.map", "Bag.map"] | ||
-- ["base.List.filter", "base.List.map"] -> ["filter", "map"] | ||
minimalUniqueSuffix :: Names -> Names |
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 initially thought I would need this, but it's easier to handle within the PPE layer so this is currently unused.
I'd prefer to just leave it here since it may be useful in the future, but happy to remove it if it seems clutter-full
@@ -312,99 +312,11 @@ GET /api/getDefinition?names=%23qkhkl0n238&relativeTo=nested | |||
}, | |||
"typeDefinitions": {} | |||
} | |||
-- Should find definitions by hash, using global names if no names in specified path. | |||
-- Should filter out any definitions which aren't in the provided namespace even if the hash matches. |
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 believe these old semantics were sub-optimal anyways, if you specifically search for a hash within a specific namespace, I think you should only get hashes that are in that namespace. If you want to do a global search for a hash you can just search at the namespace root.
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 need another PR which PREFERS local names by hash, but will fall back to global names, biased towards the current perspective.
This is so you can click on external names in a pretty-printed definition.
Awesome @ChrisPenner exactly what I鈥檇 hoped for. I鈥檒l let other folks weigh in on the code changes, but the new behavior looks great! |
@ChrisPenner just wanted to ask you about https://share-next.unison-lang.org/users/unison/code/latest/namespaces/public/base/main/;/terms/abilities/Random/shuffle Notice that
I'm not sure if your other names-related PR addresses this (or if this one does but it's just not deployed yet), but we should never show a name for a definition from outside the current perspective if that definition has a name within the current perspective. |
-- - 'local' includes ONLY the names within the provided path | ||
-- - 'ppe' is a ppe which searches for a name within the path first, but falls back to a global name search. | ||
-- The 'suffixified' component of this ppe will search for the shortest unambiguous suffix within the scope in which the name is found (local, falling back to global) | ||
scopedNamesForBranchHash :: forall m v a. Monad m => Codebase m v a -> Maybe (Branch.CausalHash) -> Path -> Backend m (Names, Names, Names, PPE.PrettyPrintEnvDecl) |
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.
Do we use the first two return values anywhere?
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 think we still need to compute them to make the PPE, but no I don't think I need to return them, I can change that 馃憤馃徏
Are you sure? I'm seeing different hashes for these: I think the I do think I need to re-evaluate how we filter out 'hash-only' queries though 馃 |
Good call. You're right. I just tracked down why these are different, and it looks like I'll fixup the docs in base. Update: this is done and looks good now: https://share-next.unison-lang.org/users/unison/code/latest/namespaces/public/base/main/;/terms/abilities/Random/shuffle |
cb71ded
to
de778d4
Compare
rootTermNamesByPath mayNamespace = do | ||
let (namespace, subnamespace) = case mayNamespace of | ||
Nothing -> ("", "*") | ||
Just namespace -> (namespace, globEscape namespace <> ".*") |
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 wonder if we should escape namespace
too, in case we go back to allowing things like Int.*.doc
? In fact, I wonder if we should escape .
characters in name segments for that reason, too.
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.
namespace
isn't being passed to a GLOB
, it's used in an equality comparison, so there's no need to escape it, or did you mean something else?
Nothing -> (mempty, [(n, ref)]) | ||
Just stripped -> ([(Name.makeRelative stripped, ref)], mempty) | ||
Nothing -> error $ "Expected name to be in namespace" <> show (n, reverse reversedPathSegments) | ||
Just stripped -> (Name.makeRelative stripped, ref) |
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'm wondering if the Name.makeRelative
is necessary here - aren't all of these names relative, even those that we put in absoluteExternalNames
? Or - if they get converted to absolute names at some point - where does that happen?
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.
To be honest I think we have a lot of unnecessary work going on with names but it's extremely difficult to get my head around it and make too many changes at once without breaking everything and not knowing why haha.
I think what I envision is that actually names objects should probably just have all absolutely qualified names, then the PPE should make them relative and/or suffixify them when it's time to display them.
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.
Approving with the disclaimer that I don't totally understand what's going on, even after the call 馃槄
My understanding is really just: things were very wrong before, now after a lot of changes, they are better, but not optimal.
Overview
Names are really confusing, currently the 'show definition by name' endpoint constructs a names object relative to where it's supposed to be, but still includes 'fall-backs' for all external names. When you call to get a definition by name, the server returns all matches, and the frontend picks on and renders it.
Problems:
Fix
relativeTo
, we now strictly limit any returned terms to names that actually exist within that namespace.Additional changes:
namespace
column on the names index.Old view of
trunk.Seq
The names we're getting here are actually from a completely different definition than the one we asked for 馃槵
New view of
trunk.Seq
frompublic.distributed
Here we can see that we still get some less-desirable names here, there are multiple
Seq
's in the current scope,collab.Seq
andtrunk.Seq
are the same hash, butcollab.Seq
is preferred simply because it's earlier alphabetically.I have an idea for fixing this problem too, but I'll split that into a separate PR if I can figure it out.
New view of
Seq
frompublic.distributed.trunk
Now that we're within the perspective of
trunk
all of the names are properly minimally prefixed and what we expect!