git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
2323: Sort IDE-generated explicit imports (#2413)

* 2323 sort IDE-generated explicit imports * make basic formatting/function choice changes before restructuring * Convert Ord DeclarationRef to sort function. Change ordering to match that suggested by linter. Compare PositionedDeclarationRef with itself by the inner ref. * update test for new ordering inferred from linter * sort linter suggested imports. always collapse ide-suggested dtors * 2323 collapse even single-dtor imports in an open import

commit6675280b8633c2382845993ef81929d844273e41 authorbbqbaron <osiris1723@gmail.com> dateMon 7 Nov 2016, 09:54 (10 years ago) parent854069c
5 files changed+77−14
src/Language/PureScript/AST/Declarations.hs+25 src/Language/PureScript/Ide/Imports.hs+3−8 src/Language/PureScript/Linter/Imports.hs+1−1 tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs+2−2 tests/Language/PureScript/Ide/ImportsSpec.hs+46−3
src/Language/PureScript/AST/Declarations.hs+25
@@ -261,6 +261,31 @@ instance Eq DeclarationRef where
261261 r == (PositionedDeclarationRef _ _ r') = r == r'
262262 _ == _ = False
263263
264+-- enable sorting lists of explicitly imported refs when suggesting imports in linting, IDE, etc.
265+-- not an Ord because this implementation is not consistent with its Eq instance.
266+-- think of it as a notion of contextual, not inherent, ordering.
267+compDecRef :: DeclarationRef -> DeclarationRef -> Ordering
268+compDecRef (TypeRef name _) (TypeRef name' _) = compare name name'
269+compDecRef (TypeOpRef name) (TypeOpRef name') = compare name name'
270+compDecRef (ValueRef ident) (ValueRef ident') = compare ident ident'
271+compDecRef (ValueOpRef name) (ValueOpRef name') = compare name name'
272+compDecRef (TypeClassRef name) (TypeClassRef name') = compare name name'
273+compDecRef (TypeInstanceRef ident) (TypeInstanceRef ident') = compare ident ident'
274+compDecRef (ModuleRef name) (ModuleRef name') = compare name name'
275+compDecRef (ReExportRef name _) (ReExportRef name' _) = compare name name'
276+compDecRef (PositionedDeclarationRef _ _ ref) ref' = compDecRef ref ref'
277+compDecRef ref (PositionedDeclarationRef _ _ ref') = compDecRef ref ref'
278+compDecRef ref ref' = compare
279+ (orderOf ref) (orderOf ref')
280+ where
281+ orderOf :: DeclarationRef -> Int
282+ orderOf (TypeClassRef _) = 0
283+ orderOf (TypeOpRef _) = 1
284+ orderOf (TypeRef _ _) = 2
285+ orderOf (ValueRef _) = 3
286+ orderOf (ValueOpRef _) = 4
287+ orderOf _ = 5
288+
264289getTypeRef :: DeclarationRef -> Maybe (ProperName 'TypeName, Maybe [ProperName 'ConstructorName])
265290getTypeRef (TypeRef name dctors) = Just (name, dctors)
266291getTypeRef (PositionedDeclarationRef _ _ r) = getTypeRef r
src/Language/PureScript/Ide/Imports.hs+3−8
@@ -202,7 +202,7 @@ addExplicitImport' decl moduleName imports =
202202 refFromDeclaration (IdeDeclTypeClass n) =
203203 P.TypeClassRef n
204204 refFromDeclaration (IdeDeclDataConstructor dtor) =
205− P.TypeRef (dtor ^. ideDtorTypeName) (Just [dtor ^. ideDtorName])
205+ P.TypeRef (dtor ^. ideDtorTypeName) Nothing
206206 refFromDeclaration (IdeDeclType t) =
207207 P.TypeRef (t ^. ideTypeName) (Just [])
208208 refFromDeclaration (IdeDeclValueOperator op) =
@@ -216,7 +216,7 @@ addExplicitImport' decl moduleName imports =
216216 -- TypeDeclaration "Maybe" + Data.Maybe (maybe) -> Data.Maybe(Maybe, maybe)
217217 insertDeclIntoImport :: IdeDeclaration -> Import -> Import
218218 insertDeclIntoImport decl' (Import mn (P.Explicit refs) Nothing) =
219− Import mn (P.Explicit (insertDeclIntoRefs decl' refs)) Nothing
219+ Import mn (P.Explicit (sortBy P.compDecRef (insertDeclIntoRefs decl' refs))) Nothing
220220 insertDeclIntoImport _ is = is
221221
222222 insertDeclIntoRefs :: IdeDeclaration -> [P.DeclarationRef] -> [P.DeclarationRef]
@@ -228,12 +228,7 @@ addExplicitImport' decl moduleName imports =
228228 refs
229229 insertDeclIntoRefs dr refs = nubBy ((==) `on` P.prettyPrintRef) (refFromDeclaration dr : refs)
230230
231− insertDtor dtor (P.TypeRef tn' dtors) =
232− case dtors of
233− Just dtors' -> P.TypeRef tn' (Just (ordNub (dtor : dtors')))
234− -- This means the import was opened. We don't add anything in this case
235− -- import Data.Maybe (Maybe(..)) -> import Data.Maybe (Maybe(Just))
236− Nothing -> P.TypeRef tn' Nothing
231+ insertDtor _ (P.TypeRef tn' _) = P.TypeRef tn' Nothing
237232 insertDtor _ refs = refs
238233
239234 matchType :: P.ProperName 'P.TypeName -> P.DeclarationRef -> Bool
src/Language/PureScript/Linter/Imports.hs+1−1
@@ -308,7 +308,7 @@ findUsedRefs env mni qn names =
308308 typesRefs
309309 = map (flip TypeRef (Just [])) typesWithoutDctors
310310 ++ map (\(ty, ds) -> TypeRef ty (Just ds)) (M.toList typesWithDctors)
311− in classRefs ++ typeOpRefs ++ typesRefs ++ valueRefs ++ valueOpRefs
311+ in sortBy compDecRef $ classRefs ++ typeOpRefs ++ typesRefs ++ valueRefs ++ valueOpRefs
312312
313313 where
314314
tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs+2−2
@@ -57,10 +57,10 @@ spec = beforeAll_ setup . describe "Adding imports" $ do
5757 outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (class ATypeClass)"])
5858 it "adds an explicit unqualified import (dataconstructor)" $ do
5959 withSupportFiles (Integration.addImport "MyJust")
60− outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyMaybe(MyJust))"])
60+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyMaybe(..))"])
6161 it "adds an explicit unqualified import (newtype)" $ do
6262 withSupportFiles (Integration.addImport "MyNewtype")
63− outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyNewtype(MyNewtype))"])
63+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyNewtype(..))"])
6464 it "adds an explicit unqualified import (typeclass member function)" $ do
6565 withSupportFiles (Integration.addImport "typeClassFun")
6666 outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (typeClassFun)"])
tests/Language/PureScript/Ide/ImportsSpec.hs+46−3
@@ -73,6 +73,8 @@ spec = do
7373 prettyPrintImportSection (addExplicitImport' (IdeDeclValueOperator (IdeValueOperator op (P.Qualified Nothing (Left (P.Ident ""))) 2 P.Infix Nothing)) mn is)
7474 addDtorImport i t mn is =
7575 prettyPrintImportSection (addExplicitImport' (IdeDeclDataConstructor (IdeDataConstructor (P.ProperName i) t wildcard)) mn is)
76+ addTypeImport i mn is =
77+ prettyPrintImportSection (addExplicitImport' (IdeDeclType (IdeType (P.ProperName i) P.Star)) mn is)
7678 it "adds an implicit unqualified import" $
7779 shouldBe
7880 (addImplicitImport' simpleFileImports (P.moduleNameFromString "Data.Map"))
@@ -100,20 +102,26 @@ spec = do
100102 shouldBe
101103 (addOpImport (P.OpName "<~>") (P.moduleNameFromString "Data.Array") explicitImports)
102104 [ "import Prelude"
103− , "import Data.Array ((<~>), tail)"
105+ , "import Data.Array (tail, (<~>))"
104106 ]
107+ it "adds a type with constructors without automatically adding an open import of said constructors " $
108+ shouldBe
109+ (addTypeImport "Maybe" (P.moduleNameFromString "Data.Maybe") simpleFileImports)
110+ [ "import Prelude"
111+ , "import Data.Maybe (Maybe)"
112+ ]
105113 it "adds the type for a given DataConstructor" $
106114 shouldBe
107115 (addDtorImport "Just" (P.ProperName "Maybe") (P.moduleNameFromString "Data.Maybe") simpleFileImports)
108116 [ "import Prelude"
109− , "import Data.Maybe (Maybe(Just))"
117+ , "import Data.Maybe (Maybe(..))"
110118 ]
111119 it "adds a dataconstructor to an existing type import" $ do
112120 let Right (_, _, typeImports, _) = sliceImportSection (withImports ["import Data.Maybe (Maybe)"])
113121 shouldBe
114122 (addDtorImport "Just" (P.ProperName "Maybe") (P.moduleNameFromString "Data.Maybe") typeImports)
115123 [ "import Prelude"
116− , "import Data.Maybe (Maybe(Just))"
124+ , "import Data.Maybe (Maybe(..))"
117125 ]
118126 it "doesn't add a dataconstructor to an existing type import with open dtors" $ do
119127 let Right (_, _, typeImports, _) = sliceImportSection (withImports ["import Data.Maybe (Maybe(..))"])
@@ -128,3 +136,38 @@ spec = do
128136 [ "import Prelude"
129137 , "import Data.Array (tail)"
130138 ]
139+
140+ describe "explicit import sorting" $ do
141+ -- given some basic import skeleton
142+ let Right (_, _, baseImports, _) = sliceImportSection $ withImports ["import Control.Monad (ap)"]
143+ moduleName = (P.moduleNameFromString "Control.Monad")
144+ addImport imports import' = addExplicitImport' import' moduleName imports
145+ valueImport ident = (IdeDeclValue (IdeValue (P.Ident ident) wildcard))
146+ typeImport name = (IdeDeclType (IdeType (P.ProperName name) P.Star))
147+ classImport name = (IdeDeclTypeClass (P.ProperName name))
148+ dtorImport name typeName = (IdeDeclDataConstructor (IdeDataConstructor (P.ProperName name) (P.ProperName typeName) wildcard))
149+ -- expect any list of provided identifiers, when imported, to come out as specified
150+ expectSorted imports expected = shouldBe
151+ (ordNub $ map
152+ (prettyPrintImportSection . foldl addImport baseImports)
153+ (permutations imports))
154+ [expected]
155+ it "sorts class" $
156+ expectSorted (map classImport ["Applicative", "Bind"])
157+ ["import Prelude", "import Control.Monad (class Applicative, class Bind, ap)"]
158+ it "sorts value" $
159+ expectSorted (map valueImport ["unless", "where"])
160+ ["import Prelude", "import Control.Monad (ap, unless, where)"]
161+ it "sorts type, value" $
162+ expectSorted
163+ ((map valueImport ["unless", "where"]) ++ (map typeImport ["Foo", "Bar"]))
164+ ["import Prelude", "import Control.Monad (Bar, Foo, ap, unless, where)"]
165+ it "sorts class, type, value" $
166+ expectSorted
167+ ((map valueImport ["unless", "where"]) ++ (map typeImport ["Foo", "Bar"]) ++ (map classImport ["Applicative", "Bind"]))
168+ ["import Prelude", "import Control.Monad (class Applicative, class Bind, Bar, Foo, ap, unless, where)"]
169+ it "sorts types with constructors, using open imports for the constructors" $
170+ expectSorted
171+ -- the imported names don't actually have to exist!
172+ (map (uncurry dtorImport) [("Just", "Maybe"), ("Nothing", "Maybe"), ("SomeOtherConstructor", "SomeDataType")])
173+ ["import Prelude", "import Control.Monad (Maybe(..), SomeDataType(..), ap)"]