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

Commit3d47f4e

Browse files
committed
Added preliminary work for brace completion
1 parenta8d516a commit3d47f4e

File tree

2 files changed

+353
-0
lines changed

2 files changed

+353
-0
lines changed
Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
namespaceMicrosoft.VisualStudio.FSharp.Editor
4+
5+
openSystem
6+
openSystem.Collections.Generic
7+
openSystem.Collections.Immutable
8+
openSystem.Threading
9+
openSystem.Threading.Tasks
10+
openSystem.Runtime.CompilerServices
11+
12+
openMicrosoft.CodeAnalysis
13+
openMicrosoft.CodeAnalysis.Completion
14+
openMicrosoft.CodeAnalysis.Options
15+
openMicrosoft.CodeAnalysis.Text
16+
openMicrosoft.CodeAnalysis.Editor.Shared.Utilities
17+
openMicrosoft.CodeAnalysis.Shared.Extensions
18+
openMicrosoft.CodeAnalysis.Host
19+
20+
openMicrosoft.VisualStudio.FSharp.LanguageService
21+
openMicrosoft.VisualStudio.Shell
22+
openMicrosoft.VisualStudio.Shell.Interop
23+
openMicrosoft.VisualStudio.Text.BraceCompletion
24+
25+
openMicrosoft.FSharp.Compiler
26+
openMicrosoft.FSharp.Compiler.Range
27+
openMicrosoft.FSharp.Compiler.SourceCodeServices
28+
openMicrosoft.VisualStudio.Text.Operations
29+
openMicrosoft.VisualStudio.Text
30+
openMicrosoft.VisualStudio.Text.Editor
31+
openSystem.Diagnostics
32+
openSystem.Runtime.InteropServices
33+
34+
[<AutoOpen>]
35+
moduleprivateFSharpBraceCompletionSessionProviderHelpers=
36+
openSystem.Runtime.InteropServices
37+
38+
letgetLanguageService<'Twhen'T:>ILanguageServiceand'T:null>(document:Document)=
39+
match document.Projectwith
40+
|null->null
41+
| project->
42+
match project.LanguageServiceswith
43+
|null->null
44+
| languageServices->
45+
languageServices.GetService<'T>()
46+
47+
letgetCaretPoint(buffer:ITextBuffer)(session:IBraceCompletionSession)=
48+
session.TextView.Caret.Position.Point.GetPoint(buffer, PositionAffinity.Predecessor)
49+
50+
letgetCaretPosition session=
51+
session|> getCaretPoint session.SubjectBuffer
52+
53+
[<Literal>]
54+
letBraceCompletion="Brace_Completion"
55+
56+
[<AllowNullLiteral>]
57+
typeinternalIEditorBraceCompletionSession=
58+
inherit ILanguageService
59+
60+
abstractCheckOpeningPoint :IBraceCompletionSession*CancellationToken->bool
61+
62+
abstractAfterStart :IBraceCompletionSession*CancellationToken->unit
63+
64+
abstractAllowOverType :IBraceCompletionSession*CancellationToken->bool
65+
66+
abstractAfterReturn :IBraceCompletionSession*CancellationToken->unit
67+
68+
[<AllowNullLiteral>]
69+
typeinternalIEditorBraceCompletionSessionFactory=
70+
inherit ILanguageService
71+
72+
abstractTryCreateSession :Document* openingPosition:int* openingBrace:char*CancellationToken->IEditorBraceCompletionSession
73+
74+
typeinternalBraceCompletionSession
75+
(
76+
textView: ITextView,
77+
subjectBuffer: ITextBuffer,
78+
openingPoint: SnapshotPoint,
79+
openingBrace: char,
80+
closingBrace: char,
81+
undoHistory: ITextUndoHistory,
82+
editorOperationsFactoryService: IEditorOperationsFactoryService,
83+
session: IEditorBraceCompletionSession
84+
)=
85+
86+
let mutableclosingPoint= subjectBuffer.CurrentSnapshot.CreateTrackingPoint(openingPoint.Position, PointTrackingMode.Positive)
87+
let mutableopeningPoint:ITrackingPoint=null
88+
leteditorOperations= editorOperationsFactoryService.GetEditorOperations(textView)
89+
90+
memberthis.EndSession()=
91+
closingPoint<-null
92+
openingPoint<-null
93+
94+
member__.CreateUndoTransaction()=
95+
undoHistory.CreateTransaction(BraceCompletion)
96+
97+
memberthis.Start(cancellationToken:CancellationToken)=
98+
// this is where the caret should go after the change
99+
letpos= textView.Caret.Position.BufferPosition
100+
letbeforeTrackingPoint= pos.Snapshot.CreateTrackingPoint(pos.Position, PointTrackingMode.Negative)
101+
102+
let mutablesnapshot= subjectBuffer.CurrentSnapshot
103+
letclosingSnapshotPoint= closingPoint.GetPoint(snapshot)
104+
105+
if closingSnapshotPoint.Position<1then
106+
Debug.Fail("The closing point was not found at the expected position.")
107+
this.EndSession()
108+
else
109+
110+
letopeningSnapshotPoint= closingSnapshotPoint.Subtract(1)
111+
112+
if openingSnapshotPoint.GetChar()<> openingBracethen
113+
// there is a bug in editor brace completion engine on projection buffer that already fixed in vs_pro. until that is FIed to use
114+
// I will make this not to assert
115+
// Debug.Fail("The opening brace was not found at the expected position.");
116+
this.EndSession()
117+
else
118+
119+
openingPoint<- snapshot.CreateTrackingPoint(openingSnapshotPoint.Position, PointTrackingMode.Positive)
120+
let_document= snapshot.GetOpenDocumentInCurrentContextWithChanges()
121+
122+
ifnot(session.CheckOpeningPoint(this, cancellationToken))then
123+
this.EndSession()
124+
else
125+
126+
use undo= this.CreateUndoTransaction()
127+
128+
snapshot<-
129+
use edit= subjectBuffer.CreateEdit()
130+
131+
if edit.HasFailedChangesthen
132+
Debug.Fail("Unable to insert closing brace")
133+
134+
// exit without setting the closing point which will take us off the stack
135+
edit.Cancel()
136+
undo.Cancel()
137+
snapshot
138+
else
139+
edit.Apply()// FIXME: perhaps, it should be ApplyAndLogExceptions()
140+
141+
letbeforePoint= beforeTrackingPoint.GetPoint(textView.TextSnapshot)
142+
143+
// switch from positive to negative tracking so it stays against the closing brace
144+
closingPoint<- subjectBuffer.CurrentSnapshot.CreateTrackingPoint(closingPoint.GetPoint(snapshot).Position, PointTrackingMode.Negative)
145+
146+
Debug.Assert(closingPoint.GetPoint(snapshot).Position>0&&(SnapshotSpan(closingPoint.GetPoint(snapshot).Subtract(1),1)).GetText().Equals(closingBrace.ToString()),
147+
"The closing point does not match the closing brace character")
148+
149+
// move the caret back between the braces
150+
textView.Caret.MoveTo(beforePoint)|> ignore
151+
152+
session.AfterStart(this, cancellationToken)
153+
154+
undo.Complete()
155+
156+
memberthis.HasNoForwardTyping(caretPoint:SnapshotPoint,endPoint:SnapshotPoint)=
157+
Debug.Assert(caretPoint.Snapshot= endPoint.Snapshot,"snapshots do not match")
158+
159+
if caretPoint.Snapshot= endPoint.Snapshotthen
160+
if caretPoint= endPointthen
161+
true
162+
else
163+
if caretPoint.Position< endPoint.Positionthen
164+
letspan= SnapshotSpan(caretPoint, endPoint)
165+
String.IsNullOrWhiteSpace(span.GetText())
166+
else
167+
false
168+
else
169+
false
170+
171+
memberthis.HasForwardTyping=
172+
letclosingSnapshotPoint= closingPoint.GetPoint(subjectBuffer.CurrentSnapshot)
173+
174+
if closingSnapshotPoint.Position>0then
175+
letcaretPos= getCaretPosition this
176+
177+
if caretPos.HasValue&&not(this.HasNoForwardTyping(caretPos.Value, closingSnapshotPoint.Subtract(1)))then
178+
true
179+
else
180+
false
181+
else
182+
false
183+
184+
member__.MoveCaretToClosingPoint()=
185+
letclosingSnapshotPoint= closingPoint.GetPoint(subjectBuffer.CurrentSnapshot)
186+
187+
// find the position just after the closing brace in the view's text buffer
188+
letafterBrace=
189+
textView.BufferGraph.MapUpToBuffer(closingSnapshotPoint, PointTrackingMode.Negative, PositionAffinity.Predecessor, textView.TextBuffer)
190+
191+
Debug.Assert(afterBrace.HasValue,"Unable to move caret to closing point")
192+
193+
if afterBrace.HasValuethen
194+
textView.Caret.MoveTo(afterBrace.Value)|> ignore
195+
196+
197+
interface IBraceCompletionSessionwith
198+
199+
memberthis.Start()=
200+
// Brace completion is not cancellable.
201+
this.Start(CancellationToken.None)
202+
203+
memberthis.PreBackspace handledCommand=
204+
handledCommand<-false
205+
206+
letcaretPos= getCaretPosition this
207+
letsnapshot= subjectBuffer.CurrentSnapshot
208+
209+
if caretPos.HasValue&& caretPos.Value.Position>0&&
210+
caretPos.Value.Position-1= openingPoint.GetPoint(snapshot).Position&&
211+
not this.HasForwardTypingthen
212+
213+
use undo= this.CreateUndoTransaction()
214+
use edit= subjectBuffer.CreateEdit()
215+
216+
letspan= SnapshotSpan(openingPoint.GetPoint(snapshot), closingPoint.GetPoint(snapshot))
217+
218+
edit.Delete(span.Span)|> ignore
219+
220+
if edit.HasFailedChangesthen
221+
edit.Cancel()
222+
undo.Cancel()
223+
Debug.Fail("Unable to clear braces")
224+
else
225+
// handle the command so the backspace does
226+
// not go through since we've already cleared the braces
227+
handledCommand<-true
228+
edit.Apply()|> ignore// FIXME: ApplyAndLogExceptions()
229+
undo.Complete()
230+
this.EndSession()
231+
232+
member__.PostBackspace()=()
233+
234+
memberthis.PreOverType handledCommand=
235+
handledCommand<-false
236+
237+
if closingPoint<>nullthen
238+
// Brace completion is not cancellable.
239+
letcancellationToken= CancellationToken.None
240+
letsnapshot= subjectBuffer.CurrentSnapshot
241+
let_document= snapshot.GetOpenDocumentInCurrentContextWithChanges()
242+
243+
letclosingSnapshotPoint= closingPoint.GetPoint(snapshot)
244+
ifnot this.HasForwardTyping&& session.AllowOverType(this, cancellationToken)then
245+
letcaretPos= getCaretPosition this
246+
247+
Debug.Assert(caretPos.HasValue&& caretPos.Value.Position< closingSnapshotPoint.Position)
248+
249+
// ensure that we are within the session before clearing
250+
if caretPos.HasValue&& caretPos.Value.Position< closingSnapshotPoint.Position&& closingSnapshotPoint.Position>0then
251+
252+
use undo= this.CreateUndoTransaction()
253+
254+
letspan= SnapshotSpan(caretPos.Value, closingSnapshotPoint.Subtract(1))
255+
256+
use edit= subjectBuffer.CreateEdit()
257+
258+
edit.Delete(span.Span)|> ignore
259+
260+
if edit.HasFailedChangesthen
261+
Debug.Fail("Unable to clear closing brace")
262+
edit.Cancel()
263+
undo.Cancel()
264+
else
265+
handledCommand<-true
266+
edit.Apply()|> ignore// FIXME: ApplyAndLogExceptions()
267+
this.MoveCaretToClosingPoint()
268+
editorOperations.AddAfterTextBufferChangePrimitive()
269+
undo.Complete()
270+
271+
member__.PostOverType()=()
272+
273+
memberthis.PreTab handledCommand=
274+
handledCommand<-false
275+
276+
ifnot this.HasForwardTypingthen
277+
handledCommand<-true
278+
279+
use undo= this.CreateUndoTransaction()
280+
281+
editorOperations.AddBeforeTextBufferChangePrimitive()
282+
this.MoveCaretToClosingPoint()
283+
editorOperations.AddAfterTextBufferChangePrimitive()
284+
undo.Complete()
285+
286+
member__.PreReturn handledCommand=
287+
handledCommand<-false
288+
289+
memberthis.PostReturn()=
290+
letcaretPos= getCaretPosition this
291+
292+
if caretPos.HasValuethen
293+
letclosingSnapshotPoint= closingPoint.GetPoint(subjectBuffer.CurrentSnapshot)
294+
295+
if closingSnapshotPoint.Position>0&& this.HasNoForwardTyping(caretPos.Value, closingSnapshotPoint.Subtract(1))then
296+
session.AfterReturn(this, CancellationToken.None)
297+
298+
member__.Finish()=()
299+
300+
member__.PostTab()=()
301+
302+
member__.PreDelete handledCommand=
303+
handledCommand<-false
304+
305+
member__.PostDelete()=()
306+
307+
member__.OpeningBrace= openingBrace
308+
309+
member__.ClosingBrace= closingBrace
310+
311+
member__.OpeningPoint= openingPoint
312+
313+
member__.ClosingPoint= closingPoint
314+
315+
member__.SubjectBuffer= subjectBuffer
316+
317+
member__.TextView= textView
318+
319+
typeinternalBraceCompletionSessionProvider
320+
(
321+
undoManager: ITextBufferUndoManagerProvider,
322+
_editorOperationsFactoryService: IEditorOperationsFactoryService
323+
)=
324+
325+
inherit ForegroundThreadAffinitizedObject()
326+
327+
interface IBraceCompletionSessionProviderwith
328+
329+
memberthis.TryCreateSession(textView,openingPoint,openingBrace,_closingBrace,session)=
330+
this.AssertIsForeground();
331+
332+
lettextSnapshot= openingPoint.Snapshot
333+
334+
session<-
335+
match textSnapshot.GetOpenDocumentInCurrentContextWithChanges()with
336+
|null->null
337+
| document->
338+
match getLanguageService<IEditorBraceCompletionSessionFactory> documentwith
339+
|null->null
340+
| editorSessionFactory->
341+
// Brace completion is (currently) not cancellable.
342+
letcancellationToken= CancellationToken.None
343+
344+
match editorSessionFactory.TryCreateSession(document, openingPoint.Position, openingBrace, cancellationToken)with
345+
|null->null
346+
|_editorSession->
347+
let_undoHistory= undoManager.GetTextBufferUndoManager(textView.TextBuffer).TextBufferUndoHistory
348+
null
349+
350+
match sessionwith
351+
|null->false
352+
|_->true

‎vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
<CompileInclude="CodeFix\FixIndexerAccess.fs" />
9999
<CompileInclude="CodeFix\RenameParamToMatchSignature.fs" />
100100
<CompileInclude="Build\SetGlobalPropertiesForSdkProjects.fs" />
101+
<CompileInclude="AutomaticCompletion\BraceCompletionSessionProvider.fs" />
101102
</ItemGroup>
102103

103104
<ItemGroup>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp