@@ -38,38 +38,39 @@ type internal FSharpColorizationService() =
3838
3939 static let DataCache = ConditionalWeakTable< SourceText, SourceTextData>()
4040
41- static let compilerTokenToRoslynToken ( colorKind : FSharpTokenColorKind ) : string =
42- match colorKind with
43- | FSharpTokenColorKind.Comment -> ClassificationTypeNames.Comment
44- | FSharpTokenColorKind.Identifier -> ClassificationTypeNames.Identifier
45- | FSharpTokenColorKind.Keyword -> ClassificationTypeNames.Keyword
46- | FSharpTokenColorKind.String -> ClassificationTypeNames.StringLiteral
47- | FSharpTokenColorKind.Text -> ClassificationTypeNames.Text
48- | FSharpTokenColorKind.UpperIdentifier -> ClassificationTypeNames.Identifier
49- | FSharpTokenColorKind.Number -> ClassificationTypeNames.NumericLiteral
50- | FSharpTokenColorKind.InactiveCode -> ClassificationTypeNames.ExcludedCode
51- | FSharpTokenColorKind.PreprocessorKeyword -> ClassificationTypeNames.PreprocessorKeyword
52- | FSharpTokenColorKind.Operator -> ClassificationTypeNames.Operator
53- | FSharpTokenColorKind.TypeName -> ClassificationTypeNames.ClassName
54- | FSharpTokenColorKind.Default | _ -> ClassificationTypeNames.Text
55-
56- static let scanAndColorNextToken ( lineTokenizer : FSharpLineTokenizer , colorMap : string [], lexState : Ref < FSharpTokenizerLexState >) : Option < FSharpTokenInfo > =
57- let tokenInfoOption , nextLexState = lineTokenizer.ScanToken( lexState.Value)
58- lexState.Value <- nextLexState
59- if tokenInfoOption.IsSome then
60- let classificationType = compilerTokenToRoslynToken( tokenInfoOption.Value.ColorClass)
61- for i = tokenInfoOption.Value.LeftColumn to tokenInfoOption.Value.RightColumn do
62- Array.set colorMap i classificationType
63- tokenInfoOption
64-
6541 static let scanSourceLine ( sourceTokenizer : FSharpSourceTokenizer , textLine : TextLine , lineContents : string , lexState : FSharpTokenizerLexState ) : SourceLineData =
42+
6643 let colorMap = Array.create textLine.Span.Length ClassificationTypeNames.Text
6744 let lineTokenizer = sourceTokenizer.CreateLineTokenizer( lineContents)
6845
46+ let compilerTokenToRoslynToken ( colorKind : FSharpTokenColorKind ) : string =
47+ match colorKind with
48+ | FSharpTokenColorKind.Comment -> ClassificationTypeNames.Comment
49+ | FSharpTokenColorKind.Identifier -> ClassificationTypeNames.Identifier
50+ | FSharpTokenColorKind.Keyword -> ClassificationTypeNames.Keyword
51+ | FSharpTokenColorKind.String -> ClassificationTypeNames.StringLiteral
52+ | FSharpTokenColorKind.Text -> ClassificationTypeNames.Text
53+ | FSharpTokenColorKind.UpperIdentifier -> ClassificationTypeNames.Identifier
54+ | FSharpTokenColorKind.Number -> ClassificationTypeNames.NumericLiteral
55+ | FSharpTokenColorKind.InactiveCode -> ClassificationTypeNames.ExcludedCode
56+ | FSharpTokenColorKind.PreprocessorKeyword -> ClassificationTypeNames.PreprocessorKeyword
57+ | FSharpTokenColorKind.Operator -> ClassificationTypeNames.Operator
58+ | FSharpTokenColorKind.TypeName -> ClassificationTypeNames.ClassName
59+ | FSharpTokenColorKind.Default | _ -> ClassificationTypeNames.Text
60+
61+ let scanAndColorNextToken ( lineTokenizer : FSharpLineTokenizer , lexState : Ref < FSharpTokenizerLexState >) : Option < FSharpTokenInfo > =
62+ let tokenInfoOption , nextLexState = lineTokenizer.ScanToken( lexState.Value)
63+ lexState.Value <- nextLexState
64+ if tokenInfoOption.IsSome then
65+ let classificationType = compilerTokenToRoslynToken( tokenInfoOption.Value.ColorClass)
66+ for i = tokenInfoOption.Value.LeftColumn to tokenInfoOption.Value.RightColumn do
67+ Array.set colorMap i classificationType
68+ tokenInfoOption
69+
6970 let previousLextState = ref( lexState)
70- let mutable tokenInfoOption = scanAndColorNextToken( lineTokenizer, colorMap , previousLextState)
71+ let mutable tokenInfoOption = scanAndColorNextToken( lineTokenizer, previousLextState)
7172 while tokenInfoOption.IsSome do
72- tokenInfoOption <- scanAndColorNextToken( lineTokenizer, colorMap , previousLextState)
73+ tokenInfoOption <- scanAndColorNextToken( lineTokenizer, previousLextState)
7374
7475 let mutable startPosition = 0
7576 let mutable endPosition = startPosition
@@ -85,7 +86,48 @@ type internal FSharpColorizationService() =
8586 startPosition <- endPosition
8687
8788 SourceLineData( previousLextState.Value, lineContents.GetHashCode(), classifiedSpans)
88-
89+
90+ static member GetColorizationData ( sourceText : SourceText , textSpan : TextSpan , fileName : Option < string >, defines : string list , cancellationToken : CancellationToken ) : List < ClassifiedSpan > =
91+ try
92+ let sourceTokenizer = FSharpSourceTokenizer( defines, fileName)
93+ let sourceTextData = DataCache.GetValue( sourceText, fun key -> SourceTextData( key.Lines.Count))
94+
95+ let startLine = sourceText.Lines.GetLineFromPosition( textSpan.Start) .LineNumber
96+ let endLine = sourceText.Lines.GetLineFromPosition( textSpan.End) .LineNumber
97+
98+ // Get the last cached scanned line
99+ let mutable scanStartLine = startLine
100+ while scanStartLine > 0 && sourceTextData.Lines.[ scanStartLine - 1 ]. IsNone do
101+ scanStartLine <- scanStartLine - 1
102+
103+ let result = new List< ClassifiedSpan>()
104+ let mutable lexState = if scanStartLine = 0 then 0 L else sourceTextData.Lines.[ scanStartLine - 1 ]. Value.LexStateAtEndOfLine
105+
106+ for i = scanStartLine to sourceText.Lines.Count - 1 do
107+ cancellationToken.ThrowIfCancellationRequested()
108+
109+ let textLine = sourceText.Lines.[ i]
110+ let lineContents = textLine.Text.ToString( textLine.Span)
111+ let lineHashCode = lineContents.GetHashCode()
112+
113+ let mutable lineData = sourceTextData.Lines.[ i]
114+ if lineData.IsNone || lineData.Value.HashCode <> lineHashCode then
115+ lineData <- Some( scanSourceLine( sourceTokenizer, textLine, lineContents, lexState))
116+
117+ lexState <- lineData.Value.LexStateAtEndOfLine
118+ sourceTextData.Lines.[ i] <- lineData
119+
120+ if startLine <= i && i <= endLine then
121+ result.AddRange( lineData.Value.ClassifiedSpans |> Seq.filter( fun token ->
122+ textSpan.Contains( token.TextSpan.Start) ||
123+ textSpan.Contains( token.TextSpan.End - 1 ) ||
124+ ( token.TextSpan.Start <= textSpan.Start && textSpan.End <= token.TextSpan.End)))
125+
126+ result
127+ with ex ->
128+ Assert.Exception( ex)
129+ reraise()
130+
89131 interface IEditorClassificationService with
90132
91133 member this.AddLexicalClassifications ( text : SourceText , textSpan : TextSpan , result : List < ClassifiedSpan >, cancellationToken : CancellationToken ) =
@@ -94,8 +136,11 @@ type internal FSharpColorizationService() =
94136 member this.AddSyntacticClassificationsAsync ( document : Document , textSpan : TextSpan , result : List < ClassifiedSpan >, cancellationToken : CancellationToken ) =
95137 document.GetTextAsync( cancellationToken) .ContinueWith(
96138 fun ( sourceTextTask : Task < SourceText >) ->
139+ let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject( document.Project)
140+ let defines = CompilerEnvironment.GetCompilationDefinesForEditing( document.Name, options.OtherOptions |> Seq.toList)
141+
97142 if sourceTextTask.Status = TaskStatus.RanToCompletion then
98- result.AddRange( FSharpColorizationService.GetColorizationData( sourceTextTask.Result, textSpan, None, [] , cancellationToken))
143+ result.AddRange( FSharpColorizationService.GetColorizationData( sourceTextTask.Result, textSpan, None, defines , cancellationToken))
99144 , cancellationToken)
100145
101146 // FSROSLYNTODO: Due to issue 12732 on Roslyn side, semantic classification is tied to C#/VB only.
@@ -130,44 +175,3 @@ type internal FSharpColorizationService() =
130175 tokens.First()
131176 else
132177 new ClassifiedSpan( ClassificationTypeNames.WhiteSpace, classifiedSpan.TextSpan)
133-
134- static member GetColorizationData ( sourceText : SourceText , textSpan : TextSpan , fileName : Option < string >, defines : string list , cancellationToken : CancellationToken ) : List < ClassifiedSpan > =
135- try
136- let sourceTokenizer = FSharpSourceTokenizer( defines, fileName)
137- let sourceTextData = DataCache.GetValue( sourceText, fun key -> SourceTextData( key.Lines.Count))
138-
139- let startLine = sourceText.Lines.GetLineFromPosition( textSpan.Start) .LineNumber
140- let endLine = sourceText.Lines.GetLineFromPosition( textSpan.End) .LineNumber
141-
142- // Get the last cached scanned line
143- let mutable scanStartLine = startLine
144- while scanStartLine > 0 && sourceTextData.Lines.[ scanStartLine - 1 ]. IsNone do
145- scanStartLine <- scanStartLine - 1
146-
147- let result = new List< ClassifiedSpan>()
148- let mutable lexState = if scanStartLine = 0 then 0 L else sourceTextData.Lines.[ scanStartLine - 1 ]. Value.LexStateAtEndOfLine
149-
150- for i = scanStartLine to sourceText.Lines.Count - 1 do
151- cancellationToken.ThrowIfCancellationRequested()
152-
153- let textLine = sourceText.Lines.[ i]
154- let lineContents = textLine.Text.ToString( textLine.Span)
155- let lineHashCode = lineContents.GetHashCode()
156-
157- let mutable lineData = sourceTextData.Lines.[ i]
158- if lineData.IsNone || lineData.Value.HashCode <> lineHashCode then
159- lineData <- Some( scanSourceLine( sourceTokenizer, textLine, lineContents, lexState))
160-
161- lexState <- lineData.Value.LexStateAtEndOfLine
162- sourceTextData.Lines.[ i] <- lineData
163-
164- if startLine <= i && i<= endLine then
165- result.AddRange( lineData.Value.ClassifiedSpans |> Seq.filter( fun token ->
166- textSpan.Contains( token.TextSpan.Start) ||
167- textSpan.Contains( token.TextSpan.End - 1 ) ||
168- ( token.TextSpan.Start <= textSpan.Start && textSpan.End <= token.TextSpan.End)))
169-
170- result
171- with ex ->
172- Assert.Exception( ex)
173- reraise()
0 commit comments