internal static Color GetFragmentTypeColor(CodeFragment.Type code) { int index = ((int)code); if (index < 0 || (index >= CodeFragment.colorTable.Length)) return Colors.Red; return CodeFragment.colorTable[index]; }
/// <summary>Checks for a given modifier e.g. 'private' in the given fragment of code.</summary> /// <param name="fragment">The fragment to check.</param> /// <param name="modifier">The modifier to check for.</param> /// <returns>True if this fragment contained the given modifier. The fragment is also removed from the code.</returns> public static bool Check(CodeFragment fragment,string modifier){ if(fragment==null||fragment.GetType()!=typeof(VariableFragment)){ return false; } bool result=(((VariableFragment)fragment).Value==modifier); if(result){ fragment.Remove(); } return result; }
/// <summary>Skips over any modifiers found in the given code fragment, returning the first non-modifier fragment found.</summary> /// <param name="fragment">The place to start from.</param> /// <returns>The first non-modifier fragment found. May be the given fragment if it is not a modifier.</returns> public static CodeFragment Skip(CodeFragment fragment){ if(fragment==null||fragment.GetType()!=typeof(VariableFragment)){ return fragment; } VariableFragment vfragment=(VariableFragment)fragment; if(vfragment.Value=="private"){ if(fragment.NextChild==null){ vfragment.Error("Error: 'private' is an access modifier and it must be followed by something. (e.g. private var i..)"); } return Skip(fragment.NextChild); } return fragment; }
private void FormatFragment(CodeFragment fragment, string content, Paragraph paragraph) { Run textRun = new Run(content); Color textColor = Colors.Black; if (null != fragment) textColor = CodeFragment.GetFragmentColor(fragment.CodeType); textRun.Foreground = new SolidColorBrush(textColor); paragraph.Inlines.Add(textRun); if (content.Contains('\n')) paragraph.Inlines.Add(new LineBreak()); }
/// <summary> /// Shows the numeric slider for the first time when there has been a mouse click on a number. /// </summary> /// <param name="cursor">The cursor position at which the mouse click occurred.</param> private void ShowNumericSlider() { System.Drawing.Point cursor = textCore.CursorPosition; // Get the fragment on which the cursor has been placed. textCore.GetFragment(cursor.X, cursor.Y, out fragmentNumber); if (null == fragmentNumber || (fragmentNumber.CodeType != CodeFragment.Type.Number)) { // Fragment is not numeric, hide the slider. if (null != numericSliderPopup) numericSliderPopup.IsOpen = false; return; } if (numericSliderPopup == null) { numericSlider = new NumericSlider(); numericSlider.UpdateSliderValue += new SliderValueUpdated(OnSliderValueUpdated); // Set the alignment of the slider. numericSlider.HorizontalAlignment = System.Windows.HorizontalAlignment.Left; numericSlider.VerticalAlignment = System.Windows.VerticalAlignment.Top; numericSlider.Width = 172; numericSlider.Height = 40; numericSliderPopup = new ExtensionPopup(this); numericSliderPopup.Child = numericSlider; numericSliderPopup.IsOpen = false; } // Set the SliderMode to double if the fragment contains a decimal point in it. numericSlider.numSliderMode = NumericSlider.SliderMode.Integer; if (fragmentNumber.Text.Contains('.')) numericSlider.numSliderMode = NumericSlider.SliderMode.Double; // Check if the current fragment is '-' sign(fragment type is also Number) // and get the next fragment to set the SliderMode. if (fragmentNumber.Text == "-") { // @TODO(Suba): Use a GetNextFragment that takes "CodeFragment". CodeFragment nextFragment; //textCore.GetNextFragment(fragmentNumber, out nextFragment); textCore.GetFragment(cursor.X + 1, cursor.Y, out nextFragment); if (nextFragment == null) return; numericSlider.numSliderMode = NumericSlider.SliderMode.Integer; if (nextFragment.Text.Contains('.')) numericSlider.numSliderMode = NumericSlider.SliderMode.Double; // Set the currentFragment to be the fragment containing the "number" instead of "-" fragmentNumber = nextFragment; } numericSliderPopup.Placement = PlacementMode.Custom; numericSliderPopup.PlacementTarget = textEditorCanvas; numericSliderPopup.CursorPosition = cursor; numericSliderPopup.IsOpen = true; System.Windows.Input.Keyboard.Focus(numericSlider); numericSlider.SetCurrentPointOnScreen(cursor); // Get the previous fragment to determine if it is a '-' sign to set the Slider value. // @TODO(Suba): Make this to take CodeFragment instead. textCore.GetPreviousFragment(fragmentNumber.ColStart, fragmentNumber.Line, out fragmentSign); // If the mode is integer then you set the slider value by calling the ResetSlider which takes an 'int' // and if it is a Double value then you call the ResetSlider which takes in a 'double' if (numericSlider.numSliderMode == NumericSlider.SliderMode.Integer) { if (fragmentSign.Text.Equals("-")) numericSlider.ResetSlider(textEditorControl, (-1) * Convert.ToInt32(fragmentNumber.Text)); else { fragmentSign = null; numericSlider.ResetSlider(textEditorControl, Convert.ToInt32(fragmentNumber.Text)); } } else { if (fragmentSign.Text.Equals("-")) numericSlider.ResetSlider(textEditorControl, (-1.0) * Convert.ToDouble(fragmentNumber.Text)); else { fragmentSign = null; numericSlider.ResetSlider(textEditorControl, Convert.ToDouble(fragmentNumber.Text)); } } }
protected virtual bool OnMouseHoverCore(CodeFragment variable = null) { return false; }
/// <summary> /// Event to handle a MouseHover - this is in reference to a MouseOver /// and held there till a timer ticks after a certain interval. Such an /// event doesn't exist and therefore it a compound combination of two /// events, labelled MouseHover /// </summary> /// <param name="validHover"></param> /// <param name="variable"></param> /// <returns></returns> public bool OnMouseHover(CodeFragment fragment) { return OnMouseHoverCore(fragment); }
public static bool IsCallableSpecialization(CodeFragment fragment) => fragment?.Kind != null && fragment.IncludeInCompilation && ( fragment.Kind.IsBodyDeclaration || fragment.Kind.IsAdjointDeclaration || fragment.Kind.IsControlledDeclaration || fragment.Kind.IsControlledAdjointDeclaration);
protected override bool OnMouseHoverCore(CodeFragment variable) { if (fragmentPointer == variable) { if (null == variable) return true; // If we are looking at the same variable since we last checked, // and the variable is not 'null', we may need to bring up the // inspection tooltip anyway (since it may not have been created). // // Non-null variable, and the inspection tooltip is visible, then // there's nothing to do. Otherwise we need to proceed to create it. if (false != inspectionToolTipPopup.IsOpen) return true; } fragmentPointer = variable; // A valid hover is defined as a Hover over a variable, and the hover lasts an entire time // determined by the inspectionToolTipTimer in the TextEditorControl if (variable == null) { Logger.LogInfo("OnMouseHoverCore", "null"); if ((null != inspectionToolTipPopup) && inspectionToolTipPopup.IsOpen) { if (inspectionToolTipPopup.IsMouseOver != true) { // The cursor is outside of the tooltip when "variable == null" // (which means the mouse hovers over an empty spot in the text // editor canvas), we'll handle this by hiding the popup and // setting the focus back onto the canvas. // inspectionToolTip.DeactivateTooltip(); inspectionToolTipPopup.IsOpen = false; System.Windows.Input.Keyboard.Focus(this.textEditorCanvas); } return true; // Notification handled. } return true; // Notification handled. } else { Logger.LogInfo("OnMouseHoverCore", variable.Text); if (variable.CodeType != CodeFragment.Type.Local) { if (null != inspectionToolTip) inspectionToolTip.DeactivateTooltip(); if (null != inspectionToolTipPopup) inspectionToolTipPopup.IsOpen = false; System.Windows.Input.Keyboard.Focus(this.textEditorCanvas); return true; // We only allow inspection of variable. } EnsureToolTipCreated(); inspectionToolTipPopup.IsOpen = false; if (inspectionToolTip.ActivateTooltip(variable.Text)) { inspectionToolTip.Width = inspectionToolTip.GetWidth(); inspectionToolTip.Height = inspectionToolTip.GetHeight(); inspectionToolTipPopup.Placement = PlacementMode.Custom; inspectionToolTipPopup.PlacementTarget = textEditorCanvas; inspectionToolTipPopup.CursorPosition = new System.Drawing.Point() { X = fragmentPointer.ColStart, Y = fragmentPointer.Line }; inspectionToolTipPopup.IsOpen = true; System.Windows.Input.Keyboard.Focus(inspectionToolTip); } return true; } }
/// <summary>Looks for 'private' before the given fragment. If found, it's also removed.</summary> /// <param name="fragment">The fragment to check before.</param> /// <param name="isPublic">True if private was not found.</param> public static void Handle(CodeFragment fragment,out bool isPublic){ isPublic=!Modifiers.Check(fragment.PreviousChild,"private"); }
/// <summary> /// Returns true if the fragment has a delimiting character and the given position occurs after it. /// </summary> private static bool IsPositionAfterDelimiter( FileContentManager file, CodeFragment fragment, Position position) => fragment.FollowedBy != CodeFragment.MissingDelimiter && GetDelimiterPosition(file, fragment) < position;
private string GetImportedFileName(CodeFragment importFragment) { if (null == importFragment || (importFragment.CodeType != CodeFragment.Type.Keyword)) return string.Empty; if (importFragment.Text != "import") return string.Empty; CodeFragment bracketFragment = null; if (textCore.GetNextFragment(importFragment, out bracketFragment) == 0) return string.Empty; if (null == bracketFragment || (bracketFragment.Text != "(")) return string.Empty; CodeFragment fileNameFragment = null; if (textCore.GetNextFragment(bracketFragment, out fileNameFragment) == 0) return string.Empty; if (null == fileNameFragment || (fileNameFragment.CodeType != CodeFragment.Type.Text)) return string.Empty; string quoted = fileNameFragment.Text; if (string.IsNullOrEmpty(quoted) || (quoted.Length <= 2)) return string.Empty; return quoted.Substring(1, quoted.Length - 2); }
public static bool IsOpenDirective(CodeFragment fragment) => fragment?.Kind != null && fragment.IncludeInCompilation && fragment.Kind.IsOpenDirective;
int CalculateCaretPosition(int currentOffset) { if (codeFragment != null) { int diff = currentOffset - codeFragment.StartRealOffset; int off = codeFragment.StartOffset + diff; if (diff >= 0 && off <= codeFragment.EndOffset) { return(off); } } KeyValuePair <int, GeneratedCodeMapping> map; // If it's first line of code, create a default temp mapping, and use it until next reparse if (currentMappings.Count == 0) { string newLine = "\r\n#line 0 \r\n "; HiddenDoc.Editor.Insert(defaultPosition, newLine); map = new KeyValuePair <int, GeneratedCodeMapping> (0, new GeneratedCodeMapping(currentOffset - 1, 0, 0, 0, 0)); currentMappings.Add(map); } else { var result = currentMappings.Where(m => m.Value.StartOffset <= currentOffset); if (!result.Any()) { return(defaultPosition); } map = result.Last(); } string pattern = "#line " + map.Key + " "; int pos = HiddenDoc.Editor.Document.Text.IndexOf(pattern); if (pos == -1 || !map.Value.StartOffset.HasValue) { return(defaultPosition); } int startRealOff = map.Value.StartOffset.Value; int offDifference = currentOffset - (startRealOff + map.Value.CodeLength); var line = HiddenDoc.Editor.Document.GetLineByOffset(pos); int endHiddenOff = line.NextLine.Offset + map.Value.StartGeneratedColumn + map.Value.CodeLength; int hiddenOff; // If off is inside the map if (offDifference <= 0) { int delta = currentOffset - startRealOff; hiddenOff = line.NextLine.Offset + map.Value.StartGeneratedColumn + delta - 1; codeFragment = new CodeFragment(hiddenOff, currentOffset, endHiddenOff); } else { // It's a new code fragment - create a temp mapping, and use it until next reparse int key = currentMappings.Last().Key + 1; string newLine = "\r\n#line " + key + " \r\n "; int newOff = endHiddenOff; if (HiddenDoc.Editor.GetCharAt(newOff) == '\n') { newOff++; } // We start a new mapping right after the preceding one, but need to include the difference // between mapping's start and the current offset HiddenDoc.Editor.Insert(newOff, newLine); HiddenDoc.Editor.Insert(newOff + newLine.Length, new String(' ', offDifference) + " \r\n"); var newMap = new KeyValuePair <int, GeneratedCodeMapping> (key, new GeneratedCodeMapping( startRealOff + map.Value.CodeLength, 0, 0, 0, offDifference)); currentMappings.Add(newMap); hiddenOff = newOff + newLine.Length + offDifference; codeFragment = new CodeFragment(newOff + newLine.Length, newMap.Value.StartOffset.Value, newOff + newLine.Length + offDifference); } return(hiddenOff); }
/// <summary> /// Returns true if the given token is fully included in the given range. /// </summary> internal static bool IsWithinRange(this CodeFragment token, Range range) => range.Contains(token.Range.Start) && range.ContainsEnd(token.Range.End);
protected override bool OnMouseHoverCore(CodeFragment variable) { if (fragmentPointer == variable) { if (null == variable) { return(true); } // If we are looking at the same variable since we last checked, // and the variable is not 'null', we may need to bring up the // inspection tooltip anyway (since it may not have been created). // // Non-null variable, and the inspection tooltip is visible, then // there's nothing to do. Otherwise we need to proceed to create it. if (false != inspectionToolTipPopup.IsOpen) { return(true); } } fragmentPointer = variable; // A valid hover is defined as a Hover over a variable, and the hover lasts an entire time // determined by the inspectionToolTipTimer in the TextEditorControl if (variable == null) { Logger.LogInfo("OnMouseHoverCore", "null"); if ((null != inspectionToolTipPopup) && inspectionToolTipPopup.IsOpen) { if (inspectionToolTipPopup.IsMouseOver != true) { // The cursor is outside of the tooltip when "variable == null" // (which means the mouse hovers over an empty spot in the text // editor canvas), we'll handle this by hiding the popup and // setting the focus back onto the canvas. // inspectionToolTip.DeactivateTooltip(); inspectionToolTipPopup.IsOpen = false; System.Windows.Input.Keyboard.Focus(this.textEditorCanvas); } return(true); // Notification handled. } return(true); // Notification handled. } else { Logger.LogInfo("OnMouseHoverCore", variable.Text); if (variable.CodeType != CodeFragment.Type.Local) { if (null != inspectionToolTip) { inspectionToolTip.DeactivateTooltip(); } if (null != inspectionToolTipPopup) { inspectionToolTipPopup.IsOpen = false; } System.Windows.Input.Keyboard.Focus(this.textEditorCanvas); return(true); // We only allow inspection of variable. } EnsureToolTipCreated(); inspectionToolTipPopup.IsOpen = false; if (inspectionToolTip.ActivateTooltip(variable.Text)) { inspectionToolTip.Width = inspectionToolTip.GetWidth(); inspectionToolTip.Height = inspectionToolTip.GetHeight(); inspectionToolTipPopup.Placement = PlacementMode.Custom; inspectionToolTipPopup.PlacementTarget = textEditorCanvas; inspectionToolTipPopup.CursorPosition = new System.Drawing.Point() { X = fragmentPointer.ColStart, Y = fragmentPointer.Line }; inspectionToolTipPopup.IsOpen = true; System.Windows.Input.Keyboard.Focus(inspectionToolTip); } return(true); } }
int CalculateCaretPosition (int currentOffset) { if (codeFragment != null) { int diff = currentOffset - codeFragment.StartRealOffset; int off = codeFragment.StartOffset + diff; if (diff >= 0 && off <= codeFragment.EndOffset) return off; } KeyValuePair<int, GeneratedCodeMapping> map; var defaultPosition = GetDefaultPosition (); if (defaultPosition < 0) { defaultPosition = 0; } // If it's first line of code, create a default temp mapping, and use it until next reparse if (currentMappings.Count == 0) { string newLine = "\r\n#line 0 \r\n "; HiddenDoc.Editor.Insert (defaultPosition, newLine); map = new KeyValuePair<int, GeneratedCodeMapping> (0, new GeneratedCodeMapping (currentOffset - 1, 0, 0, 0, 0)); currentMappings.Add (map); } else { var result = currentMappings.Where (m => m.Value.StartOffset <= currentOffset); if (!result.Any ()) return defaultPosition; map = result.Last (); } string pattern = "#line " + map.Key + " "; int pos = HiddenDoc.Editor.Document.IndexOf (pattern, 0, HiddenDoc.Editor.Document.TextLength, StringComparison.Ordinal); if (pos == -1 || !map.Value.StartOffset.HasValue) return defaultPosition; int startRealOff = map.Value.StartOffset.Value; int offDifference = currentOffset - (startRealOff + map.Value.CodeLength); var line = HiddenDoc.Editor.Document.GetLineByOffset (pos); int endHiddenOff = line.NextLine.Offset + map.Value.StartGeneratedColumn + map.Value.CodeLength; int hiddenOff; // If off is inside the map if (offDifference <= 0) { int delta = currentOffset - startRealOff; hiddenOff = line.NextLine.Offset + map.Value.StartGeneratedColumn + delta - 1; codeFragment = new CodeFragment (hiddenOff, currentOffset, endHiddenOff); } else { // It's a new code fragment - create a temp mapping, and use it until next reparse int key = currentMappings.Last ().Key + 1; string newLine = "\r\n#line " + key + " \r\n "; int newOff = endHiddenOff; if (HiddenDoc.Editor.GetCharAt (newOff) == '\n') newOff++; // We start a new mapping right after the preceding one, but need to include the difference // between mapping's start and the current offset HiddenDoc.Editor.Insert (newOff, newLine); HiddenDoc.Editor.Insert (newOff + newLine.Length, new String (' ', offDifference) + " \r\n"); var newMap = new KeyValuePair<int, GeneratedCodeMapping> (key, new GeneratedCodeMapping ( startRealOff + map.Value.CodeLength, 0, 0, 0, offDifference)); currentMappings.Add (newMap); hiddenOff = newOff + newLine.Length + offDifference; codeFragment = new CodeFragment (newOff + newLine.Length, newMap.Value.StartOffset.Value, newOff + newLine.Length + offDifference); } return hiddenOff; }
public static GeneratedCode WithCodeFragment(this GeneratedCode @this, CodeFragment fragment) => new(@this.Language, @this.CodeFragments.Append(fragment));
public static bool IsTypeDeclaration(CodeFragment fragment) => fragment?.Kind != null && fragment.IncludeInCompilation && fragment.Kind.IsTypeDefinition;
/// <summary> /// Makes all the necessary changes to TextBuffer and CodeFragment once the slider value has been changed. /// Calls function SetFragmentText to change the value of the CodeFragment and takes in arguments to /// accordingly ColEnd of the CodeFragment. /// Calls function ModifyText to replace the text in the TextBuffer to show the change in the value of the /// slider. It takes in the entire line to be replaced in the TextBuffer as an argument and makes the change. /// </summary> private void HandleSliderValueChanged() { int sliderValue = 0; double sliderValueD = 0; // FragmentSign contains the fragment which contains the '-' sign // and FragmentNumber contains the fragment with the number value. if (fragmentNumber != null && fragmentNumber.CodeType == CodeFragment.Type.Number) { // Retrieve the current line content from the TextBuffer. string oldLineContent = textCore.CurrentTextBuffer.GetLineContent(fragmentNumber.Line); string newLineContent = oldLineContent; //fragmentSignLineContent = textCore.CurrentTextBuffer.GetLineContent(fragmentSign.Line); string numSliderValue = null; if (numericSlider.numSliderMode == NumericSlider.SliderMode.Integer) { // Get the new slider value to change the line content to contain it. sliderValue = numericSlider.intValue; newLineContent = newLineContent.Remove(fragmentNumber.ColStart, fragmentNumber.ColEnd - fragmentNumber.ColStart + 1); numSliderValue = sliderValue.ToString(); // Calls the Mirror to set the value of the number during RunTime. Solution.Current.ExecutionSession.SetValue(fragmentNumber.Line, fragmentNumber.ColStart, sliderValue); // Reset the slider to show the new value. numericSlider.ResetSlider(textEditorControl, sliderValue); } else { // Round the number to 4 decimal places. sliderValueD = numericSlider.doubleValue; sliderValueD = Math.Round(sliderValueD, 4); newLineContent = newLineContent.Remove(fragmentNumber.ColStart, fragmentNumber.ColEnd - fragmentNumber.ColStart + 1); Solution.Current.ExecutionSession.SetValue(fragmentNumber.Line, fragmentNumber.ColStart, sliderValueD); numSliderValue = sliderValueD.ToString(); numericSlider.ResetSlider(textEditorControl, sliderValueD); } // If the number is originally a negative number with the fragment containing the '-' sign in FragmentSign // Then replace it by a space as the Fragment text and the line content in the TextBuffer have been updated // to contain the '-' sign automatically. // Insert the new slider value into the line content. if (fragmentSign != null) { // Remove the '-' sign from TextBuffer as well ('-' has a length of 1) if (fragmentSign.Line == fragmentNumber.Line) { if (fragmentNumber.ColStart == fragmentSign.ColEnd + 1) { newLineContent = newLineContent.Remove(fragmentSign.ColStart, 1); textCore.SetFragmentText(fragmentSign.ColStart, fragmentSign.Line, string.Empty); newLineContent = newLineContent.Insert(fragmentSign.ColStart, numSliderValue); fragmentSign = null; } else { newLineContent = newLineContent.Remove(fragmentSign.ColStart, 1); //newLineContent = newLineContent.Remove(fragmentSign.ColStart, fragmentNumber.ColStart-fragmentSign.ColEnd-1); textCore.SetFragmentText(fragmentSign.ColStart, fragmentSign.Line, string.Empty); newLineContent = newLineContent.Insert(fragmentNumber.ColStart , numSliderValue); fragmentSign = null; } } else { newLineContent = newLineContent.Insert(fragmentSign.ColStart, numSliderValue); textCore.SetFragmentText(fragmentSign.ColStart, fragmentSign.Line, string.Empty); string fragmentSignLineContent = textCore.CurrentTextBuffer.GetLineContent(fragmentSign.Line); fragmentSignLineContent = fragmentSignLineContent.Remove(fragmentSign.ColStart, 1); textCore.CurrentTextBuffer.ModifyText(fragmentSign.Line, fragmentSignLineContent); fragmentSign = null; } } else { newLineContent = newLineContent.Insert(fragmentNumber.ColStart, numSliderValue); } // Set the fragment text with the new slider value. textCore.SetFragmentText(fragmentNumber.ColStart, fragmentNumber.Line, numSliderValue); // Replace the old line content with the new line content. textCore.CurrentTextBuffer.ModifyText(fragmentNumber.Line, newLineContent); Logger.LogInfo("SliderChange", fragmentNumber.Line.ToString() + " => " + newLineContent); } numericSlider.ValueChanged = false; }
public static bool IsCallableDeclaration(CodeFragment fragment) => fragment?.Kind != null && fragment.IncludeInCompilation && ( fragment.Kind.IsOperationDeclaration || fragment.Kind.IsFunctionDeclaration);
/// <summary> /// Returns the completion environment at the given position in the file or null if the environment cannot be /// determined. Stores the code fragment found at or before the given position into an out parameter. /// </summary> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// <exception cref="ArgumentException">Thrown when the position is invalid.</exception> private static (CompletionScope, QsFragmentKind) GetCompletionEnvironment( FileContentManager file, Position position, out CodeFragment fragment) { if (file == null) { throw new ArgumentNullException(nameof(file)); } if (!Utils.IsValidPosition(position)) { throw new ArgumentException(nameof(position)); } if (!Utils.IsValidPosition(position, file)) { // FileContentManager.IndentationAt will fail if the position is not within the file. fragment = null; return(null, null); } var token = GetTokenAtOrBefore(file, position); if (token == null) { fragment = null; return(null, null); } fragment = token.GetFragment(); var relativeIndentation = fragment.Indentation - file.IndentationAt(position); QsCompilerError.Verify(Math.Abs(relativeIndentation) <= 1); var parents = new[] { token }.Concat(token.GetNonEmptyParents()) .Skip(relativeIndentation + 1) .Select(t => t.GetFragment()); CompletionScope scope = null; if (!parents.Any()) { scope = CompletionScope.TopLevel; } else if (parents.Any() && parents.First().Kind.IsNamespaceDeclaration) { scope = CompletionScope.NamespaceTopLevel; } else if (parents.Where(parent => parent.Kind.IsFunctionDeclaration).Any()) { scope = CompletionScope.Function; } else if (parents.Any() && parents.First().Kind.IsOperationDeclaration) { scope = CompletionScope.OperationTopLevel; } else if (parents.Where(parent => parent.Kind.IsOperationDeclaration).Any()) { scope = CompletionScope.Operation; } QsFragmentKind previous = null; if (relativeIndentation == 0 && IsPositionAfterDelimiter(file, fragment, position)) { previous = fragment.Kind; } else if (relativeIndentation == 0) { previous = token.PreviousOnScope()?.GetFragment().Kind; } else if (relativeIndentation == 1) { previous = token.GetNonEmptyParent()?.GetFragment().Kind; } return(scope, previous); }