@@ -2,24 +2,30 @@ module HsBindgen.Frontend.Pass.Select (
22 selectDecls
33 ) where
44
5+ import Data.List (sortBy )
56import Data.Map.Strict qualified as Map
7+ import Data.Ord (comparing )
68import Data.Set ((\\) )
79import Data.Set qualified as Set
810
911import Clang.HighLevel.Types
12+ import Clang.Paths
1013
1114import HsBindgen.Errors (panicPure )
1215import HsBindgen.Frontend.Analysis.DeclIndex (DeclIndex (.. ), Match ,
1316 selectDeclIndex )
1417import HsBindgen.Frontend.Analysis.DeclIndex qualified as DeclIndex
1518import HsBindgen.Frontend.Analysis.DeclUseGraph qualified as DeclUseGraph
19+ import HsBindgen.Frontend.Analysis.IncludeGraph (IncludeGraph )
20+ import HsBindgen.Frontend.Analysis.IncludeGraph qualified as IncludeGraph
1621import HsBindgen.Frontend.Analysis.UseDeclGraph (UseDeclGraph )
1722import HsBindgen.Frontend.Analysis.UseDeclGraph qualified as UseDeclGraph
1823import HsBindgen.Frontend.AST.Coerce (CoercePass (coercePass ))
1924import HsBindgen.Frontend.AST.Internal qualified as C
2025import HsBindgen.Frontend.Naming qualified as C
2126import HsBindgen.Frontend.Pass
2227import HsBindgen.Frontend.Pass.ConstructTranslationUnit.IsPass
28+ import HsBindgen.Frontend.Pass.HandleMacros.Error
2329import HsBindgen.Frontend.Pass.Parse.IsPass
2430import HsBindgen.Frontend.Pass.ResolveBindingSpecs.IsPass
2531import HsBindgen.Frontend.Pass.Select.IsPass
@@ -164,11 +170,15 @@ selectDecls
164170 , C. unitAnn = unitAnn
165171 }
166172
167- in ( unitSelect
168- , selectMsgs
173+ msgs :: [Msg Select ]
174+ msgs =
175+ selectMsgs
176+ ++ getDelayedMsgs selectedIndex
169177 -- If there were no predicate matches we issue a warning to the user.
170178 ++ [ SelectNoDeclarationsMatched | Set. null rootIds ]
171- ++ getDelayedMsgs selectedIndex
179+
180+ in ( unitSelect
181+ , sortSelectMsgs unitIncludeGraph msgs
172182 )
173183 where
174184 notAttempted , failed , failedMacros :: Set DeclId
@@ -320,3 +330,63 @@ getDelayedMsgs DeclIndex{..} = concat [
320330
321331 getMsgss :: (a -> [b ]) -> Map k a -> [b ]
322332 getMsgss f = concatMap f . Map. elems
333+
334+ {- ------------------------------------------------------------------------------
335+ Sort messages
336+ -------------------------------------------------------------------------------}
337+
338+ type OrderMap = Map SourcePath Int
339+
340+ buildOrderMap :: Ord a => [a ] -> Map a Int
341+ buildOrderMap xs = Map. fromList (zip xs [0 .. ])
342+
343+ -- [Performance]: Working with hashed source paths (hash them once) and a
344+ -- `HashMap` may be a bit faster.
345+ compareByOrder :: OrderMap -> SourcePath -> SourcePath -> Ordering
346+ compareByOrder xs x y =
347+ let ix = lookupUnsafe x
348+ iy = lookupUnsafe y
349+ in compare ix iy
350+ where
351+ lookupUnsafe z = case Map. lookup z xs of
352+ Nothing -> panicPure $ " unknown source path: " <> show z
353+ Just v -> v
354+
355+ compareSingleLocs :: OrderMap -> SingleLoc -> SingleLoc -> Ordering
356+ compareSingleLocs xs x y =
357+ case compareByOrder xs (singleLocPath x) (singleLocPath y) of
358+ LT -> LT
359+ EQ -> comparing getLineCol x y
360+ GT -> GT
361+ where
362+ getLineCol :: SingleLoc -> (Int , Int )
363+ getLineCol z = (singleLocLine z, singleLocColumn z)
364+
365+ getSingleLoc :: Msg Select -> Maybe SingleLoc
366+ getSingleLoc = \ case
367+ SelectStatusInfo _ d -> fromD d
368+ TransitiveDependencyOfDeclarationUnavailable _ _ d -> fromD d
369+ SelectDeprecated d -> fromD d
370+ SelectParseSuccess m -> fromM m
371+ SelectParseNotAttempted (ParseNotAttempted m) -> fromM m
372+ SelectParseFailure (ParseFailure m) -> fromM m
373+ SelectMacroFailure (HandleMacrosParseMsg m) -> fromM m
374+ SelectNoDeclarationsMatched -> Nothing
375+ where
376+ fromD = Just . C. declLoc . C. declInfo
377+ fromM = Just . loc
378+
379+ compareMsgs :: OrderMap -> Msg Select -> Msg Select -> Ordering
380+ compareMsgs orderMap x y =
381+ case (getSingleLoc x, getSingleLoc y) of
382+ (Just lx, Just ly) -> compareSingleLocs orderMap lx ly
383+ -- Sort messages not attached to a declaration to the back.
384+ (Nothing , _ ) -> GT
385+ (_ , Nothing ) -> LT
386+
387+ sortSelectMsgs :: IncludeGraph -> [Msg Select ] -> [Msg Select ]
388+ sortSelectMsgs includeGraph = sortBy (compareMsgs orderMap)
389+ where
390+ -- Compute the order map once.
391+ orderMap :: OrderMap
392+ orderMap = buildOrderMap $ IncludeGraph. toSortedList includeGraph
0 commit comments