protected virtual int?GetSmartIndentation(ITextSnapshotLine line) { ITextSnapshot snapshot = line.Snapshot; SnapshotPoint contextEndPosition = line.Start; SnapshotPoint endPosition = line.EndIncludingLineBreak; SnapshotPoint endPositionOnLine = line.End; IReferenceAnchors anchors = FindNearestAnchors(contextEndPosition); IAnchor previous = anchors.Previous; int spanEnd = Math.Min(line.Snapshot.Length, endPosition.Position + 1); Span span; IAnchor enclosing = anchors.Enclosing; if (enclosing != null) { span = Span.FromBounds(enclosing.TrackingSpan.GetStartPoint(snapshot).Position, spanEnd); } else if (previous != null) { // at least for now, include the previous span due to the way error handling places bounds on an anchor span = Span.FromBounds(previous.TrackingSpan.GetStartPoint(snapshot).Position, spanEnd); } else { span = Span.FromBounds(0, spanEnd); } var diagnosticsPane = DiagnosticsPane; if (diagnosticsPane != null) { diagnosticsPane.WriteLine(string.Format("Smart indent from anchor span: {0}", span)); } ITokenSource bufferTokenSource = GetTokenSource(new SnapshotSpan(snapshot, span)); ITokenSource tokenSource = new CodeCompletionTokenSource(bufferTokenSource, endPosition); ITokenStream tokenStream = new CommonTokenStream(tokenSource); IDictionary <RuleContext, CaretReachedException> parseTrees = GetParseTrees(tokenStream, anchors); if (parseTrees == null) { return(null); } var indentLevels = new SortedDictionary <int, IList <KeyValuePair <RuleContext, CaretReachedException> > >(); foreach (var parseTree in parseTrees) { if (parseTree.Value == null) { continue; } IParseTree firstNodeOnLine = FindFirstNodeAfterOffset(parseTree.Key, line.Start.Position); if (firstNodeOnLine == null) { firstNodeOnLine = parseTree.Value.FinalContext; } if (firstNodeOnLine == null) { continue; } int?indentationLevel = GetIndent(parseTree, firstNodeOnLine, line.Start); if (indentationLevel == null) { continue; } IList <KeyValuePair <RuleContext, CaretReachedException> > indentList; if (!indentLevels.TryGetValue(indentationLevel.Value, out indentList)) { indentList = new List <KeyValuePair <RuleContext, CaretReachedException> >(); indentLevels[indentationLevel.Value] = indentList; } indentList.Add(parseTree); } if (indentLevels.Count == 0) { return(null); } int indentLevel = indentLevels.First().Key; if (indentLevels.Count > 1) { // TODO: resolve multiple possibilities } return(indentLevel); }
protected virtual int? GetSmartIndentation(ITextSnapshotLine line) { ITextSnapshot snapshot = line.Snapshot; SnapshotPoint contextEndPosition = line.Start; SnapshotPoint endPosition = line.EndIncludingLineBreak; SnapshotPoint endPositionOnLine = line.End; IReferenceAnchors anchors = FindNearestAnchors(contextEndPosition); IAnchor previous = anchors.Previous; int spanEnd = Math.Min(line.Snapshot.Length, endPosition.Position + 1); Span span; IAnchor enclosing = anchors.Enclosing; if (enclosing != null) { span = Span.FromBounds(enclosing.TrackingSpan.GetStartPoint(snapshot).Position, spanEnd); } else if (previous != null) { // at least for now, include the previous span due to the way error handling places bounds on an anchor span = Span.FromBounds(previous.TrackingSpan.GetStartPoint(snapshot).Position, spanEnd); } else { span = Span.FromBounds(0, spanEnd); } var diagnosticsPane = DiagnosticsPane; if (diagnosticsPane != null) diagnosticsPane.WriteLine(string.Format("Smart indent from anchor span: {0}", span)); ITokenSource bufferTokenSource = GetTokenSource(new SnapshotSpan(snapshot, span)); ITokenSource tokenSource = new CodeCompletionTokenSource(bufferTokenSource, endPosition); ITokenStream tokenStream = new CommonTokenStream(tokenSource); IDictionary<RuleContext, CaretReachedException> parseTrees = GetParseTrees(tokenStream, anchors); if (parseTrees == null) return null; var indentLevels = new SortedDictionary<int, IList<KeyValuePair<RuleContext, CaretReachedException>>>(); foreach (var parseTree in parseTrees) { if (parseTree.Value == null) continue; IParseTree firstNodeOnLine = FindFirstNodeAfterOffset(parseTree.Key, line.Start.Position); if (firstNodeOnLine == null) firstNodeOnLine = parseTree.Value.FinalContext; if (firstNodeOnLine == null) continue; int? indentationLevel = GetIndent(parseTree, firstNodeOnLine, line.Start); if (indentationLevel == null) continue; IList<KeyValuePair<RuleContext, CaretReachedException>> indentList; if (!indentLevels.TryGetValue(indentationLevel.Value, out indentList)) { indentList = new List<KeyValuePair<RuleContext, CaretReachedException>>(); indentLevels[indentationLevel.Value] = indentList; } indentList.Add(parseTree); } if (indentLevels.Count == 0) return null; int indentLevel = indentLevels.First().Key; if (indentLevels.Count > 1) { // TODO: resolve multiple possibilities } return indentLevel; }