Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3a2b23e

Browse files
authored
Escape dollar signs in completion snippets (#4745)
* Escape dollar signs in completion snippets* added Snippet* Added comments
1 parent4808791 commit3a2b23e

File tree

2 files changed

+70
-12
lines changed

2 files changed

+70
-12
lines changed

‎ghcide/src/Development/IDE/Plugin/Completions/Logic.hs‎

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import Development.IDE hiding (line)
6969
importDevelopment.IDE.Spans.AtPoint (pointCommand)
7070

7171

72+
importqualifiedDevelopment.IDE.Plugin.Completions.TypesasC
7273
importGHC.Plugins (Depth (AllTheWay),
7374
mkUserStyle,
7475
neverQualify,
@@ -202,7 +203,7 @@ mkCompl
202203
_preselect=Nothing,
203204
_sortText=Nothing,
204205
_filterText=Nothing,
205-
_insertText=Just insertText,
206+
_insertText=Just$ snippetToTextinsertText,
206207
_insertTextFormat=JustInsertTextFormat_Snippet,
207208
_insertTextMode=Nothing,
208209
_textEdit=Nothing,
@@ -242,10 +243,9 @@ mkNameCompItem doc thingParent origName provenance isInfix !imp mod = CI {..}
242243
isTypeCompl= isTcOcc origName
243244
typeText=Nothing
244245
label= stripOccNamePrefix$ printOutputable origName
245-
insertText=case isInfixof
246+
insertText=snippetText$case isInfixof
246247
Nothing-> label
247248
JustLeftSide-> label<>"`"
248-
249249
JustSurrounded-> label
250250
additionalTextEdits=
251251
imp<&>\x->
@@ -294,7 +294,7 @@ defaultCompletionItemWithLabel label =
294294
fromIdentInfo::Uri->IdentInfo->MaybeT.Text->CompItem
295295
fromIdentInfo doc identInfo@IdentInfo{..} q=CI
296296
{ compKind= occNameToComKind name
297-
, insertText=rend
297+
, insertText= snippetTextrend
298298
, provenance=DefinedInmod
299299
, label=rend
300300
, typeText=Nothing
@@ -458,10 +458,11 @@ localCompletionsForParsedModule uri pm@ParsedModule{pm_parsed_source = L _ HsMod
458458
]
459459

460460
mkLocalComp pos n ctyp ty=
461-
CI ctyppn (Local pos) pn tyNothing (ctyp`elem` [CompletionItemKind_Struct,CompletionItemKind_Interface])Nothing (Just$NameDetails (ms_mod$ pm_mod_summary pm) occ)True
461+
CI ctypsn (Local pos) pn tyNothing (ctyp`elem` [CompletionItemKind_Struct,CompletionItemKind_Interface])Nothing (Just$NameDetails (ms_mod$ pm_mod_summary pm) occ)True
462462
where
463463
occ= rdrNameOcc$ unLoc n
464464
pn= showForSnippet n
465+
sn= snippetText pn
465466

466467
findRecordCompl::Uri->Provenance->TyClDeclGhcPs-> [CompItem]
467468
findRecordCompl uri mnDataDecl {tcdLName, tcdDataDefn}= result
@@ -638,7 +639,7 @@ getCompletions
638639
dotFieldSelectorToCompl::T.Text->T.Text-> (Bool,CompItem)
639640
dotFieldSelectorToCompl recname label= (True,CI
640641
{ compKind=CompletionItemKind_Field
641-
, insertText= label
642+
, insertText=snippetTextlabel
642643
, provenance=DefinedIn recname
643644
, label= label
644645
, typeText=Nothing
@@ -667,7 +668,7 @@ getCompletions
667668
endLoc= upperRange oldPos
668669
localCompls=map (uncurry localBindsToCompItem)$ getFuzzyScope localBindings startLoc endLoc
669670
localBindsToCompItem::Name->MaybeType->CompItem
670-
localBindsToCompItem name typ=CI ctyppn thisModName pn tyNothing (not$ isValOcc occ)Nothing detsTrue
671+
localBindsToCompItem name typ=CI ctyp(snippetText pn) thisModName pn tyNothing (not$ isValOcc occ)Nothing detsTrue
671672
where
672673
occ= nameOccName name
673674
ctyp= occNameToComKind occ
@@ -736,7 +737,8 @@ uniqueCompl candidate unique =
736737
-- filter global completions when we already have a local one
737738
||not(isLocalCompletion candidate)&& isLocalCompletion unique
738739
thenEQ
739-
elsecompare (importedFrom candidate, insertText candidate) (importedFrom unique, insertText unique)
740+
elsecompare (importedFrom candidate) (importedFrom unique)<>
741+
snippetLexOrd (insertText candidate) (insertText unique)
740742
other-> other
741743
where
742744
importedFrom::CompItem->T.Text
@@ -805,9 +807,10 @@ mkRecordSnippetCompItem uri parent ctxStr compl importedFrom imp = r
805807
}
806808

807809
placeholder_pairs=zip compl ([1..]::[Int])
808-
snippet_parts=map (\(x, i)-> x<>"=${"<>T.pack (show i)<>":_"<> x<>"}") placeholder_pairs
809-
snippet=T.intercalate (T.pack",") snippet_parts
810-
buildSnippet= ctxStr<>" {"<> snippet<>"}"
810+
snippet_parts= placeholder_pairs<&>\(x, i)->
811+
snippetText x<>"="<> snippetVariableDefault (T.pack$show i) (C.SText$"_"<> x)
812+
snippet=mconcat$ intersperse"," snippet_parts
813+
buildSnippet= snippetText ctxStr<>" {"<> snippet<>"}"
811814

812815
getImportQual::LImportDeclGhcPs->MaybeT.Text
813816
getImportQual (L _ imp)

‎ghcide/src/Development/IDE/Plugin/Completions/Types.hs‎

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ import qualified Data.Text as T
1414

1515
importData.Aeson
1616
importData.Aeson.Types
17+
importData.Function (on)
1718
importData.Hashable (Hashable)
19+
importqualifiedData.ListasL
20+
importData.List.NonEmpty (NonEmpty (..))
21+
importData.String (IsString (..))
1822
importData.Text (Text)
1923
importDevelopment.IDE.GHC.Compat
2024
importDevelopment.IDE.Graph (RuleResult)
@@ -81,9 +85,60 @@ data Provenance
8185
|LocalSrcSpan
8286
deriving (Eq,Ord,Show)
8387

88+
newtypeSnippet=Snippet [SnippetAny]
89+
deriving (Eq,Show)
90+
derivingnewtype (Semigroup,Monoid)
91+
92+
instanceIsStringSnippetwhere
93+
fromString= snippetText.T.pack
94+
95+
--| @SnippetAny@ can be used to construct sanitized snippets. See the LSP
96+
-- spec for more details.
97+
dataSnippetAny
98+
=STextText
99+
--^ Literal text
100+
|STabStopInt (MaybeSnippetAny)
101+
--^ Creates a tab stop, i.e. parts of the snippet that are meant to be
102+
-- filled in by the user and that can be jumped between using the tab key.
103+
-- The optional field can be used to provide a placeholder value.
104+
|SChoiceInt (NonEmptyText)
105+
--^ Presents a choice between the provided values to the user
106+
|SVariableText (MaybeSnippetAny)
107+
--^ Snippet variable. See the spec for possible values. The optional field
108+
-- can be used to provide a default value for when the variable is not set.
109+
deriving (Eq,Show)
110+
111+
snippetText::Text->Snippet
112+
snippetText=Snippet.L.singleton.SText
113+
114+
snippetVariable::Text->Snippet
115+
snippetVariable n=Snippet.L.singleton$SVariable nNothing
116+
117+
snippetVariableDefault::Text->SnippetAny->Snippet
118+
snippetVariableDefault n d=Snippet.L.singleton.SVariable n$Just d
119+
120+
snippetToText::Snippet->Text
121+
snippetToText (Snippet l)=foldMap (snippetAnyToTextFalse) l
122+
where
123+
snippetAnyToText isNested=\case
124+
SText t-> sanitizeText isNested t
125+
STabStop i ph->"${"<>T.pack (show i)<>foldMap (\p->":"<> snippetAnyToTextTrue p) ph<>"}"
126+
SChoice i (c:| cs)->"${"<>T.pack (show i)<>"|"<> c<>foldMap (","<>) cs<>"}"
127+
SVariable n md->"${"<> n<>foldMap (\x->":"<> snippetAnyToTextTrue x) md<>"}"
128+
sanitizeText isNested=T.foldl' (sanitizeChar isNested)mempty
129+
sanitizeChar isNested t= (t<>).\case
130+
'$'->"\\$"
131+
'\\'->"\\\\"
132+
','| isNested->"\\,"
133+
'|'| isNested->"\\|"
134+
c->T.singleton c
135+
136+
snippetLexOrd::Snippet->Snippet->Ordering
137+
snippetLexOrd=compare`on` snippetToText
138+
84139
dataCompItem=CI
85140
{compKind::CompletionItemKind
86-
,insertText::T.Text--^ Snippet for the completion
141+
,insertText::Snippet--^ Snippet for the completion
87142
,provenance::Provenance--^ From where this item is imported from.
88143
,label::T.Text--^ Label to display to the user.
89144
,typeText::MaybeT.Text

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp