示例#1
0
 /// <summary>
 /// Note that the only thing that may be set to null is the fragment kind - all other properties need to be set upon initialization
 /// </summary>
 private CodeFragment(int indent, Range r, string text, char next, QsComments comments, QsFragmentKind kind, bool include)
 {
     if (!Utils.IsValidRange(r))
     {
         throw new ArgumentException("invalid range for code fragment");
     }
     if (!DelimitingChars.Contains(next) && next != MissingDelimiter)
     {
         throw new ArgumentException("a CodeFragment needs to be followed by a DelimitingChar");
     }
     this.Indentation          = indent < 0 ? throw new ArgumentException("indentation needs to be positive") : indent;
     this.Text                 = text?.TrimEnd() ?? throw new ArgumentNullException(nameof(text));
     this.FollowedBy           = next;
     this.Comments             = comments ?? QsComments.Empty;
     this.Kind                 = kind; // nothing here should be modifiable
     this.FragmentRange        = r.Copy();
     this.HeaderRange          = GetHeaderRange(this.Text, this.Kind);
     this.IncludeInCompilation = include;
 }
示例#2
0
 internal CodeFragment SetKind(QsFragmentKind kind) =>
 new CodeFragment(this.Indentation, this.Range, this.Text, this.FollowedBy, this.Comments, kind, this.IncludeInCompilation);
        /// <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);
        }
示例#4
0
 internal CodeFragment(int indent, Range r, string text, char next, QsFragmentKind kind = null) :
     this(indent, r, text, next, null, kind, true)
 {
 }
示例#5
0
 private static Tuple <QsPositionInfo, QsPositionInfo> GetHeaderRange(string text, QsFragmentKind kind) =>
 kind == null ? QsCompilerDiagnostic.DefaultRange : kind.IsControlledAdjointDeclaration
         ? Parsing.HeaderDelimiters(2).Invoke(text ?? "")
         : Parsing.HeaderDelimiters(1).Invoke(text ?? "");