Beispiel #1
0
        // TODO: we need to get the current namespace here somehow so that referenced UDT names
        // don't get expanded with the full namespace name
        /// <summary>
        /// Returns the Q# source representation of a resolved type.
        /// </summary>
        /// <param name="t">The resolved type</param>
        /// <returns>A string containing the source representation of the type</returns>
        internal static string ResolvedTypeToString(ResolvedType t)
        {
            var exprTransformer = new ExpressionToQs();
            var transformer     = new ExpressionTypeToQs(exprTransformer);

            return(transformer.Apply(t));
        }
Beispiel #2
0
        /// <summary>
        /// Returns a sequence of suggestions on how deprecated syntax can be updated based on the generated diagnostics,
        /// and given the file for which those diagnostics were generated.
        /// Returns an empty enumerable if any of the given arguments is null.
        /// </summary>
        internal static IEnumerable <(string, WorkspaceEdit)> SuggestionsForDeprecatedSyntax
            (this FileContentManager file, IEnumerable <Diagnostic> diagnostics)
        {
            if (file == null || diagnostics == null)
            {
                return(Enumerable.Empty <(string, WorkspaceEdit)>());
            }
            var deprecatedUnitTypes         = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedUnitType));
            var deprecatedNOToperators      = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedNOToperator));
            var deprecatedANDoperators      = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedANDoperator));
            var deprecatedORoperators       = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedORoperator));
            var deprecatedOpCharacteristics = diagnostics.Where(DiagnosticTools.WarningType(WarningCode.DeprecatedOpCharacteristics));

            (string, WorkspaceEdit) ReplaceWith(string text, LSP.Range range)
            {
                bool NeedsWs(Char ch) => Char.IsLetterOrDigit(ch) || ch == '_';

                if (range?.Start != null && range.End != null)
                {
                    var beforeEdit = file.GetLine(range.Start.Line).Text.Substring(0, range.Start.Character);
                    var afterEdit  = file.GetLine(range.End.Line).Text.Substring(range.End.Character);
                    if (beforeEdit.Any() && NeedsWs(beforeEdit.Last()))
                    {
                        text = $" {text}";
                    }
                    if (afterEdit.Any() && NeedsWs(afterEdit.First()))
                    {
                        text = $"{text} ";
                    }
                }
                var edit = new TextEdit {
                    Range = range?.Copy(), NewText = text
                };

                return($"Replace with \"{text.Trim()}\".", file.GetWorkspaceEdit(edit));
            }

            // update deprecated keywords and operators

            var suggestionsForUnitType = deprecatedUnitTypes.Select(d => ReplaceWith(Keywords.qsUnit.id, d.Range));
            var suggestionsForNOT      = deprecatedNOToperators.Select(d => ReplaceWith(Keywords.qsNOTop.op, d.Range));
            var suggestionsForAND      = deprecatedANDoperators.Select(d => ReplaceWith(Keywords.qsANDop.op, d.Range));
            var suggestionsForOR       = deprecatedORoperators.Select(d => ReplaceWith(Keywords.qsORop.op, d.Range));

            // update deprecated operation characteristics syntax

            var typeToQs = new ExpressionTypeToQs(new ExpressionToQs());

            string CharacteristicsAnnotation(Characteristics c)
            {
                typeToQs.onCharacteristicsExpression(SymbolResolution.ResolveCharacteristics(c));
                return($"{Keywords.qsCharacteristics.id} {typeToQs.Output}");
            }

            var suggestionsForOpCharacteristics = deprecatedOpCharacteristics.SelectMany(d =>
            {
                // TODO: TryGetQsSymbolInfo currently only returns information about the inner most leafs rather than all types etc.
                // Once it returns indeed all types in the fragment, the following code block should be replaced by the commented out code below.
                var fragment = file.TryGetFragmentAt(d.Range.Start, out var _);
                IEnumerable <Characteristics> GetCharacteristics(QsTuple <Tuple <QsSymbol, QsType> > argTuple) =>
                SyntaxGenerator.ExtractItems(argTuple).SelectMany(item => item.Item2.ExtractCharacteristics()).Distinct();
                var characteristicsInFragment =
                    fragment?.Kind is QsFragmentKind.FunctionDeclaration function ? GetCharacteristics(function.Item2.Argument) :
                    fragment?.Kind is QsFragmentKind.OperationDeclaration operation ? GetCharacteristics(operation.Item2.Argument) :
                    fragment?.Kind is QsFragmentKind.TypeDefinition type ? GetCharacteristics(type.Item2) :
                    Enumerable.Empty <Characteristics>();

                //var symbolInfo = file.TryGetQsSymbolInfo(d.Range.Start, false, out var fragment);
                //var characteristicsInFragment = (symbolInfo?.UsedTypes ?? Enumerable.Empty<QsType>())
                //    .SelectMany(t => t.ExtractCharacteristics()).Distinct();
                var fragmentStart = fragment?.GetRange()?.Start;
                return(characteristicsInFragment
                       .Where(c => c.Range.IsValue && DiagnosticTools.GetAbsoluteRange(fragmentStart, c.Range.Item).Overlaps(d.Range))
                       .Select(c => ReplaceWith(CharacteristicsAnnotation(c), d.Range)));
            });

            return(suggestionsForOpCharacteristics.ToArray()
                   .Concat(suggestionsForUnitType)
                   .Concat(suggestionsForNOT)
                   .Concat(suggestionsForAND)
                   .Concat(suggestionsForOR));
        }