private static async Task<Solution> GetTransformedSolutionAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var solution = document.Project.Solution;
            var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var expectedFileName = diagnostic.Properties[SA1649FileNameMustMatchTypeName.ExpectedFileNameKey];
            var newPath = document.FilePath != null ? Path.Combine(Path.GetDirectoryName(document.FilePath), expectedFileName) : null;

            var newDocumentId = DocumentId.CreateNewId(document.Id.ProjectId);

            var newSolution = solution
                .RemoveDocument(document.Id)
                .AddDocument(newDocumentId, expectedFileName, syntaxRoot, document.Folders, newPath);

            // Make sure to also add the file to linked projects
            foreach (var linkedDocumentId in document.GetLinkedDocumentIds())
            {
                DocumentId linkedExtractedDocumentId = DocumentId.CreateNewId(linkedDocumentId.ProjectId);
                newSolution = newSolution.AddDocument(linkedExtractedDocumentId, expectedFileName, syntaxRoot, document.Folders);
            }

            return newSolution;
        }
        private static async Task<Solution> GetTransformedSolutionAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
            BaseTypeDeclarationSyntax baseTypeDeclarationSyntax = node as BaseTypeDeclarationSyntax;
            DelegateDeclarationSyntax delegateDeclarationSyntax = node as DelegateDeclarationSyntax;
            if (baseTypeDeclarationSyntax == null && delegateDeclarationSyntax == null)
            {
                return document.Project.Solution;
            }

            DocumentId extractedDocumentId = DocumentId.CreateNewId(document.Project.Id);
            string extractedDocumentName = baseTypeDeclarationSyntax.Identifier.ValueText;
            if (baseTypeDeclarationSyntax != null)
            {
                TypeDeclarationSyntax typeDeclarationSyntax = baseTypeDeclarationSyntax as TypeDeclarationSyntax;
                if (typeDeclarationSyntax?.TypeParameterList?.Parameters.Count > 0)
                {
                    extractedDocumentName += "`" + typeDeclarationSyntax.TypeParameterList.Parameters.Count;
                }
            }
            else
            {
                if (delegateDeclarationSyntax.TypeParameterList?.Parameters.Count > 0)
                {
                    extractedDocumentName += "`" + delegateDeclarationSyntax.TypeParameterList.Parameters.Count;
                }
            }

            extractedDocumentName += ".cs";

            List<SyntaxNode> nodesToRemoveFromExtracted = new List<SyntaxNode>();
            SyntaxNode previous = node;
            for (SyntaxNode current = node.Parent; current != null; previous = current, current = current.Parent)
            {
                foreach (SyntaxNode child in current.ChildNodes())
                {
                    if (child == previous)
                    {
                        continue;
                    }

                    switch (child.Kind())
                    {
                    case SyntaxKind.NamespaceDeclaration:
                    case SyntaxKind.ClassDeclaration:
                    case SyntaxKind.StructDeclaration:
                    case SyntaxKind.InterfaceDeclaration:
                    case SyntaxKind.EnumDeclaration:
                    case SyntaxKind.DelegateDeclaration:
                        nodesToRemoveFromExtracted.Add(child);
                        break;

                    default:
                        break;
                    }
                }
            }

            SyntaxNode extractedDocumentNode = root.RemoveNodes(nodesToRemoveFromExtracted, SyntaxRemoveOptions.KeepUnbalancedDirectives);

            Solution updatedSolution = document.Project.Solution.AddDocument(extractedDocumentId, extractedDocumentName, extractedDocumentNode, document.Folders);

            // Make sure to also add the file to linked projects
            foreach (var linkedDocumentId in document.GetLinkedDocumentIds())
            {
                DocumentId linkedExtractedDocumentId = DocumentId.CreateNewId(linkedDocumentId.ProjectId);
                updatedSolution = updatedSolution.AddDocument(linkedExtractedDocumentId, extractedDocumentName, extractedDocumentNode, document.Folders);
            }

            // Remove the type from its original location
            updatedSolution = updatedSolution.WithDocumentSyntaxRoot(document.Id, root.RemoveNode(node, SyntaxRemoveOptions.KeepUnbalancedDirectives));

            return updatedSolution;
        }
		private async Task<Result> EncapsulateFieldAsync(IFieldSymbol field, Document document, bool updateReferences, CancellationToken cancellationToken)
		{
			var originalField = field;
			var finalNames = GeneratePropertyAndFieldNames(field);
			var finalFieldName = finalNames.Item1;
			var generatedPropertyName = finalNames.Item2;

			// Annotate the field declarations so we can find it after rename.
			var fieldDeclaration = field.DeclaringSyntaxReferences.First();
			var declarationAnnotation = new SyntaxAnnotation();
			document = document.WithSyntaxRoot(fieldDeclaration.SyntaxTree.GetRoot(cancellationToken).ReplaceNode(fieldDeclaration.GetSyntax(cancellationToken),
			                                                                                                      fieldDeclaration.GetSyntax(cancellationToken).WithAdditionalAnnotations(declarationAnnotation)));

			var solution = document.Project.Solution;

			foreach (var linkedDocumentId in document.GetLinkedDocumentIds())
			{
				var linkedDocument = solution.GetDocument(linkedDocumentId);
				var linkedRoot = await linkedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
				var linkedFieldNode = linkedRoot.FindNode(fieldDeclaration.Span);
				if (linkedFieldNode.Span != fieldDeclaration.Span)
				{
					continue;
				}

				var updatedRoot = linkedRoot.ReplaceNode(linkedFieldNode, linkedFieldNode.WithAdditionalAnnotations(declarationAnnotation));
				solution = solution.WithDocumentSyntaxRoot(linkedDocumentId, updatedRoot);
			}

			document = solution.GetDocument(document.Id);

			// Resolve the annotated symbol and prepare for rename.

			var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
			var compilation = semanticModel.Compilation;
			field = field.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol as IFieldSymbol;

			var solutionNeedingProperty = solution;

			// We couldn't resolve field after annotating its declaration. Bail
			if (field == null)
			{
				return null;
			}

			solutionNeedingProperty = await UpdateReferencesAsync(
				updateReferences, solution, document, field, finalFieldName, generatedPropertyName, cancellationToken).ConfigureAwait(false);
			document = solutionNeedingProperty.GetDocument(document.Id);

			var markFieldPrivate = field.DeclaredAccessibility != Accessibility.Private;
			var rewrittenFieldDeclaration = await RewriteFieldNameAndAccessibility(finalFieldName, markFieldPrivate, document, declarationAnnotation, cancellationToken).ConfigureAwait(false);

			document = await Formatter.FormatAsync(document.WithSyntaxRoot(rewrittenFieldDeclaration), Formatter.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);

			solution = document.Project.Solution;
			foreach (var linkedDocumentId in document.GetLinkedDocumentIds())
			{
				var linkedDocument = solution.GetDocument(linkedDocumentId);
				var updatedLinkedRoot = await RewriteFieldNameAndAccessibility(finalFieldName, markFieldPrivate, linkedDocument, declarationAnnotation, cancellationToken).ConfigureAwait(false);
				var updatedLinkedDocument = await Formatter.FormatAsync(linkedDocument.WithSyntaxRoot(updatedLinkedRoot), Formatter.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);
				solution = updatedLinkedDocument.Project.Solution;
			}

			document = solution.GetDocument(document.Id);

			semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
			compilation = semanticModel.Compilation;

			var newRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
			var newDeclaration = newRoot.GetAnnotatedNodes<SyntaxNode>(declarationAnnotation).First();
			field = semanticModel.GetDeclaredSymbol(newDeclaration, cancellationToken) as IFieldSymbol;

			var generatedProperty = GenerateProperty(generatedPropertyName, finalFieldName, originalField.DeclaredAccessibility, originalField, field.ContainingType, new SyntaxAnnotation(), document, cancellationToken);

			var solutionWithProperty = await AddPropertyAsync(document, document.Project.Solution, field, generatedProperty, cancellationToken).ConfigureAwait(false);

			return new Result(solutionWithProperty, originalField.ToDisplayString(), Glyph.FieldPublic);
		}
        public async Task <CompletionData> GetExpressionCompletionDataAsync(string exp, StackFrame frame, CancellationToken token)
        {
            var location = frame.SourceLocation;

            if (document == null)
            {
                return(null);
            }
            var solution     = document.Project.Solution;
            var textSnapshot = textBuffer.CurrentSnapshot;
            var text         = textSnapshot.GetText(new Span(0, textSnapshot.Length));
            var insertOffset = await GetAdjustedContextPointAsync(textSnapshot.GetLineFromLineNumber (location.EndLine - 1).Start.Position + location.EndColumn - 1, document, token).ConfigureAwait(false);

            text = text.Insert(insertOffset, ";" + exp + ";");
            insertOffset++;            //advance for 1 which represents `;` before expression
            var newTextBuffer = PlatformCatalog.Instance.TextBufferFactoryService.CreateTextBuffer(text, textBuffer.ContentType);
            var snapshot      = newTextBuffer.CurrentSnapshot;

            try {
                //Workaround Mono bug: https://github.com/mono/mono/issues/8700
                snapshot.AsText();
            } catch (Exception) {
            }

            // Fork the solution using this new primary buffer for the document and all of its linked documents.
            var forkedSolution = solution.WithDocumentText(document.Id, snapshot.AsText(), PreservationMode.PreserveIdentity);

            foreach (var link in document.GetLinkedDocumentIds())
            {
                forkedSolution = forkedSolution.WithDocumentText(link, snapshot.AsText(), PreservationMode.PreserveIdentity);
            }

            // Put it into a new workspace, and open it and its related documents
            // with the projection buffer as the text.
            var forkedWorkspace = new DebuggerIntellisenseWorkspace(forkedSolution);

            forkedWorkspace.OpenDocument(document.Id, newTextBuffer.AsTextContainer());
            foreach (var link in document.GetLinkedDocumentIds())
            {
                forkedWorkspace.OpenDocument(link, newTextBuffer.AsTextContainer());
            }
            var cs                = forkedWorkspace.Services.GetLanguageServices(LanguageNames.CSharp).GetService <CompletionService> ();
            var trigger           = new CompletionTrigger(CompletionTriggerKind.Invoke, '\0');
            var roslynCompletions = await cs.GetCompletionsAsync(forkedWorkspace.CurrentSolution.GetDocument(document.Id), insertOffset + exp.Length, trigger, cancellationToken : token).ConfigureAwait(false);

            if (roslynCompletions == null)
            {
                return(null);
            }
            var result = new Mono.Debugging.Client.CompletionData();

            foreach (var roslynCompletion in roslynCompletions.Items)
            {
                if (roslynCompletion.Tags.Contains(WellKnownTags.Snippet))
                {
                    continue;
                }
                result.Items.Add(new Mono.Debugging.Client.CompletionItem(roslynCompletion.DisplayText, RoslynTagsToDebuggerFlags(roslynCompletion.Tags)));
            }
            result.ExpressionLength = roslynCompletions.Span.Length;
            return(result);
        }
        protected override async Task<QuickInfoContent> BuildContentAsync(
            Document document,
            SyntaxToken token,
            CancellationToken cancellationToken)
        {
            var linkedDocumentIds = document.GetLinkedDocumentIds();

            var modelAndSymbols = await this.BindTokenAsync(document, token, cancellationToken).ConfigureAwait(false);
            if ((modelAndSymbols.Item2 == null || modelAndSymbols.Item2.Count == 0) && !linkedDocumentIds.Any())
            {
                return null;
            }

            if (!linkedDocumentIds.Any())
            {
                return await CreateContentAsync(document.Project.Solution.Workspace,
                    token,
                    modelAndSymbols.Item1,
                    modelAndSymbols.Item2,
                    supportedPlatforms: null,
                    cancellationToken: cancellationToken).ConfigureAwait(false);
            }

            // Linked files/shared projects: imagine the following when FOO is false
            // #if FOO
            // int x = 3;
            // #endif 
            // var y = x$$;
            //
            // 'x' will bind as an error type, so we'll show incorrect information.
            // Instead, we need to find the head in which we get the best binding, 
            // which in this case is the one with no errors.

            var candidateProjects = new List<ProjectId>() { document.Project.Id };
            var invalidProjects = new List<ProjectId>();

            var candidateResults = new List<Tuple<DocumentId, SemanticModel, IList<ISymbol>>>();
            candidateResults.Add(Tuple.Create(document.Id, modelAndSymbols.Item1, modelAndSymbols.Item2));

            foreach (var link in linkedDocumentIds)
            {
                var linkedDocument = document.Project.Solution.GetDocument(link);
                var linkedToken = await FindTokenInLinkedDocument(token, linkedDocument, cancellationToken).ConfigureAwait(false);

                if (linkedToken != default(SyntaxToken))
                {
                    // Not in an inactive region, so this file is a candidate.
                    candidateProjects.Add(link.ProjectId);
                    var linkedModelAndSymbols = await this.BindTokenAsync(linkedDocument, linkedToken, cancellationToken).ConfigureAwait(false);
                    candidateResults.Add(Tuple.Create(link, linkedModelAndSymbols.Item1, linkedModelAndSymbols.Item2));
                }
            }

            // Take the first result with no errors.
            var bestBinding = candidateResults.FirstOrDefault(c => c.Item3.Count > 0 && !ErrorVisitor.ContainsError(c.Item3.FirstOrDefault()));

            // Every file binds with errors. Take the first candidate, which is from the current file.
            if (bestBinding == null)
            {
                bestBinding = candidateResults.First();
            }

            if (bestBinding.Item3 == null || !bestBinding.Item3.Any())
            {
                return null;
            }

            // We calculate the set of supported projects
            candidateResults.Remove(bestBinding);
            foreach (var candidate in candidateResults)
            {
                // Does the candidate have anything remotely equivalent?
                if (!candidate.Item3.Intersect(bestBinding.Item3, LinkedFilesSymbolEquivalenceComparer.Instance).Any())
                {
                    invalidProjects.Add(candidate.Item1.ProjectId);
                }
            }

            var supportedPlatforms = new SupportedPlatformData(invalidProjects, candidateProjects, document.Project.Solution.Workspace);
            return await CreateContentAsync(document.Project.Solution.Workspace, token, bestBinding.Item2, bestBinding.Item3, supportedPlatforms, cancellationToken).ConfigureAwait(false);
        }