public static SyntaxTree GetSyntaxTreeSynchronously(Document document, CancellationToken cancellationToken) { //TODO: Roslyn 2.0: use document.GetSyntaxTreeSynchronously() SyntaxTree syntaxTree; if (document.TryGetSyntaxTree(out syntaxTree)) return syntaxTree; return document.GetSyntaxTreeAsync(cancellationToken).GetAwaiter().GetResult(); }
public static async Task<IEnumerable<LinePositionSpanTextChange>> GetFormattingChangesAfterKeystroke(Workspace workspace, OptionSet options, Document document, int position, char character) { var tree = await document.GetSyntaxTreeAsync(); if (character == '\n') { // format previous line on new line var lines = (await document.GetTextAsync()).Lines; var targetLine = lines[lines.GetLineFromPosition(position).LineNumber - 1]; if (!string.IsNullOrWhiteSpace(targetLine.Text.ToString(targetLine.Span))) { return await GetFormattingChangesForRange(workspace, options, document, targetLine.Start, targetLine.End); } } else if (character == '}' || character == ';') { // format after ; and } var node = FindFormatTarget(tree, position); if (node != null) { return await GetFormattingChangesForRange(workspace, options, document, node.FullSpan.Start, node.FullSpan.End); } } return Enumerable.Empty<LinePositionSpanTextChange>(); }
public async Task<QuickInfoItem> GetItemAsync( Document document, int position, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = await tree.GetTouchingTokenAsync(position, cancellationToken, findInsideTrivia: true).ConfigureAwait(false); var state = await GetQuickInfoItemAsync(document, token, position, cancellationToken).ConfigureAwait(false); if (state != null) { return state; } if (ShouldCheckPreviousToken(token)) { var previousToken = token.GetPreviousToken(); if ((state = await GetQuickInfoItemAsync(document, previousToken, position, cancellationToken).ConfigureAwait(false)) != null) { return state; } } return null; }
private static Document RemoveUnnecessaryUsings(Document doc, Compilation compilation) { #region CodeContracts Contract.Requires(doc != null); Contract.Requires(compilation != null); Contract.Ensures(Contract.Result<Document>() != null); #endregion CodeContracts var st = doc.GetSyntaxTreeAsync().Result; var sm = doc.GetSemanticModelAsync().Result; //var assembly = Assembly.LoadFrom(@"C:\cci\Microsoft.Research\Imported\Tools\Roslyn\v4.5.1\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"C:\cci\Microsoft.Research\CCTools\ReviewBot\bin\Debug\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"..\..\..\packages\Microsoft.CodeAnalysis.Features.0.7.4040207-beta\lib\net45\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"C:\Users\t-scottc\Desktop\Signed_20140201.1\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"C:\Users\t-scottc\workspace\roslyn\Binaries\Debug\Microsoft.CodeAnalysis.CSharp.Workspaces.dll"); Assembly assembly; if (TryGetMicrosoftCodeAnalysisCSharpFeatures(out assembly)) { var type = assembly.GetType("Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports.CSharpRemoveUnnecessaryImportsService"); var method = type.GetMethod("RemoveUnnecessaryImports"); var service = Activator.CreateInstance(type); return method.Invoke(service, new object[] { doc, sm, st.GetRoot(), CancellationToken.None }) as Document; } else { Output.WriteWarning("Can't run the refactoring to remove using"); return doc; } }
public async Task<ParameterHintingResult> InternalGetParameterDataProviderAsync (Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken, int recCount) { if (position == 0 || recCount > 1) return ParameterHintingResult.Empty; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var tokenLeftOfPosition = tree.FindTokenOnLeftOfPosition (position, cancellationToken); if (tokenLeftOfPosition.IsKind (SyntaxKind.LessThanToken)) { var startToken = tokenLeftOfPosition.GetPreviousToken(); return HandleTypeParameterCase(semanticModel, startToken.Parent, cancellationToken); } var context = SyntaxContext.Create(workspace, document, semanticModel, position, cancellationToken); var targetParent = context.TargetToken.Parent; if (targetParent == null) return ParameterHintingResult.Empty; if (context.TargetToken.IsKind (SyntaxKind.IdentifierName)) { targetParent = targetParent.Parent; } if (context.TargetToken.IsKind (SyntaxKind.CloseParenToken) || context.TargetToken.IsKind (SyntaxKind.CloseBracketToken) || context.TargetToken.IsKind (SyntaxKind.GreaterThanToken)) targetParent = targetParent.Parent; var node = targetParent.Parent; // case: identifier<arg1,| if (node == null) { if (context.LeftToken.Kind() == SyntaxKind.CommaToken) { targetParent = context.LeftToken.GetPreviousToken().Parent; node = targetParent.Parent; if (node.Kind() == SyntaxKind.LessThanExpression) { return HandleTypeParameterCase(semanticModel, ((BinaryExpressionSyntax)node).Left, cancellationToken); } } return ParameterHintingResult.Empty; } if (node.IsKind (SyntaxKind.Argument)) { node = node.Parent.Parent; } else { if (!(targetParent is BaseArgumentListSyntax) && !(targetParent is AttributeArgumentListSyntax) && !(targetParent is InitializerExpressionSyntax)) { if (position == targetParent.Span.Start) return ParameterHintingResult.Empty; return await InternalGetParameterDataProviderAsync (document, semanticModel, targetParent.Span.Start, cancellationToken, recCount + 1).ConfigureAwait (false); } } switch (node.Kind()) { case SyntaxKind.Attribute: return HandleAttribute(semanticModel, node, cancellationToken); case SyntaxKind.ThisConstructorInitializer: case SyntaxKind.BaseConstructorInitializer: return HandleConstructorInitializer(semanticModel, node, cancellationToken); case SyntaxKind.ObjectCreationExpression: return HandleObjectCreationExpression(semanticModel, node, cancellationToken); case SyntaxKind.InvocationExpression: return HandleInvocationExpression(semanticModel, (InvocationExpressionSyntax)node, cancellationToken); case SyntaxKind.ElementAccessExpression: return HandleElementAccessExpression(semanticModel, (ElementAccessExpressionSyntax)node, cancellationToken); } return ParameterHintingResult.Empty; }
static async Task <int> GetAdjustedContextPointAsync(int contextPoint, Document document, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // Determine the position in the buffer at which to end the tracking span representing // the part of the imaginary buffer before the text in the view. var token = tree.FindTokenOnLeftOfPosition(contextPoint, cancellationToken); // Special case to handle class designer because it asks for debugger IntelliSense using // spans between members. if (contextPoint > token.Span.End && token.IsKindOrHasMatchingText(SyntaxKind.CloseBraceToken) && token.Parent.IsKind(SyntaxKind.Block) && token.Parent.Parent is MemberDeclarationSyntax) { return(contextPoint); } if (token.IsKindOrHasMatchingText(SyntaxKind.CloseBraceToken) && token.Parent.IsKind(SyntaxKind.Block)) { return(token.SpanStart); } return(token.FullSpan.End); }
public async Task AnalyzeSyntaxAsync(Document document, CancellationToken cancellationToken) { if (!document.SupportsSyntaxTree) { return; } // getting tree is cheap since tree always stays in memory var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var length = tree.Length; while (true) { if (_map.TryAdd(document.Id, length)) { Interlocked.Add(ref _size, length); return; } long size; if (_map.TryGetValue(document.Id, out size)) { if (size == length) { return; } if (_map.TryUpdate(document.Id, length, size)) { Interlocked.Add(ref _size, length - size); return; } } } }
protected override int GetAdjustedContextPoint(int contextPoint, Document document) { // Determine the position in the buffer at which to end the tracking span representing // the part of the imagininary buffer before the text in the view. var tree = document.GetSyntaxTreeAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); var token = tree.FindTokenOnLeftOfPosition(contextPoint, CancellationToken.None); // Special case to handle class designer because it asks for debugger IntelliSense using // spans between members. if (contextPoint > token.Span.End && token.IsKindOrHasMatchingText(SyntaxKind.CloseBraceToken) && token.Parent.IsKind(SyntaxKind.Block) && token.Parent.Parent is MemberDeclarationSyntax) { return contextPoint; } if (token.IsKindOrHasMatchingText(SyntaxKind.CloseBraceToken) && token.Parent.IsKind(SyntaxKind.Block)) { return token.SpanStart; } return token.FullSpan.End; }
async Task<Solution> MoveClassIntoNewFileAsync(Document document, ClassStatementSyntax typeDecl, string className, CancellationToken cancellationToken) { // symbol representing the type var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var typeSymbol = semanticModel.GetDeclaredSymbol(typeDecl, cancellationToken); // remove type from current files var currentSyntaxTree = await document.GetSyntaxTreeAsync(); var currentRoot = await currentSyntaxTree.GetRootAsync(); //In VB you have to remove th parent of det declaration node. That is the "ClassBlockSyntax" var replacedRoot = currentRoot.RemoveNode(typeDecl.Parent, SyntaxRemoveOptions.KeepNoTrivia); document = document.WithSyntaxRoot(replacedRoot); // create new tree for a new file // we drag all the imports because we don't know which are needed // and there is no easy way to find out which var currentUsings = currentRoot.DescendantNodesAndSelf().Where(s => s is ImportsStatementSyntax); var currentNs = (NamespaceStatementSyntax)currentRoot.DescendantNodesAndSelf().First(s => s is NamespaceStatementSyntax); SyntaxList<StatementSyntax> c; if(currentNs != null) { //We have to wrap the content of the class in the namespace. var temp = SyntaxFactory.SingletonList( SyntaxFactory.NamespaceBlock( SyntaxFactory.NamespaceStatement(SyntaxFactory.ParseName(currentNs.Name.ToString())), SyntaxFactory.SingletonList(typeDecl.Parent), SyntaxFactory.EndNamespaceStatement() )); c = SyntaxFactory.List(temp.Select(i => ((StatementSyntax)i))); } else { c = SyntaxFactory.SingletonList(typeDecl.Parent); } var newFileTree = SyntaxFactory.CompilationUnit() .WithImports(SyntaxFactory.List(currentUsings.Select(i => ((ImportsStatementSyntax)i)))) .WithMembers(c) .WithoutLeadingTrivia() .NormalizeWhitespace(); var codeText = newFileTree.ToFullString(); //TODO: handle name conflicts var newDocument = document.Project.AddDocument(className, SourceText.From(codeText), document.Folders); newDocument = await RemoveUnusedImportDirectivesAsync(newDocument, cancellationToken); return newDocument.Project.Solution; }
//--- Class Methods --- private static async Task<Document> AddMissingEnumFields(Document document, SyntaxToken typeDecl, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var node = (SwitchStatementSyntax)typeDecl.Parent; IdentifierNameSyntax switchVariable; var missingMembers = EnumSwitchAnalysis.GetMissingEnumMembers(node, semanticModel, out switchVariable); if(missingMembers.Any()) { // get existing switchSections var existingSections = node.Sections.ToList(); SwitchSectionSyntax defaultSection = null; if(existingSections.Any() && existingSections.Last().DescendantNodes().OfType<DefaultSwitchLabelSyntax>().Any()) { defaultSection = existingSections.Last(); existingSections = existingSections.Take(existingSections.Count - 1).ToList(); } // generate missing case statements var switchVariableTypeInfo = semanticModel.GetTypeInfo(switchVariable); var newCaseStatements = missingMembers.Select(missingMember => SyntaxFactory.CaseSwitchLabel( SyntaxFactory.Token(SyntaxKind.CaseKeyword), SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(switchVariableTypeInfo.Type.Name), SyntaxFactory.IdentifierName(missingMember.Name) ), SyntaxFactory.Token(SyntaxKind.ColonToken) ) ).Select(caseSection => SyntaxFactory.SwitchSection( SyntaxFactory.List<SwitchLabelSyntax>(new[] { caseSection }), SyntaxFactory.List<StatementSyntax>().Add( SyntaxFactory.ThrowStatement( SyntaxFactory.ObjectCreationExpression( SyntaxFactory.ParseTypeName(nameof(NotImplementedException)), SyntaxFactory.ArgumentList(), null ) ) ) )).ToImmutableArray(); // insert case statements after the last one var tree = await document.GetSyntaxTreeAsync(cancellationToken); var root = (CompilationUnitSyntax)tree.GetRoot(cancellationToken); var switchStatement = SyntaxFactory.SwitchStatement( SyntaxFactory.IdentifierName(switchVariable.Identifier) .WithLeadingTrivia(switchVariable.GetLeadingTrivia()) .WithTrailingTrivia(switchVariable.GetTrailingTrivia()) ).WithSections( new SyntaxList<SwitchSectionSyntax>() .AddRange(existingSections) .AddRange(newCaseStatements) .AddRange(defaultSection == null ? Enumerable.Empty<SwitchSectionSyntax>() : new [] { defaultSection }) ).WithLeadingTrivia(node.GetLeadingTrivia()) .WithTrailingTrivia(node.GetTrailingTrivia()); root = root.ReplaceNode(node, switchStatement); return document.WithSyntaxRoot(root); } return document; }
/// <summary> /// The entry point to Gistify's engine. Takes the document and the extent of the selection, /// and outputs the augmented snippet. /// </summary> /// <param name="document"></param> /// <param name="startPosition"></param> /// <param name="endPosition"></param> /// <returns>String with the augmented snippet.</returns> public static string AugmentSelection(Document document, int startPosition, int endPosition) { var tree = document.GetSyntaxTreeAsync().Result; var model = document.GetSemanticModelAsync().Result; var objectInfos = DiscoveryWalker.FindObjects(tree, model, startPosition, endPosition); var augmentedSelection = SyntaxBuilder.AugmentSnippet(objectInfos, tree, startPosition, endPosition); return augmentedSelection; }
protected override async Task<bool> IsExclusiveAsync(Document document, int caretPosition, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = syntaxTree.FindTokenOnLeftOfPosition(caretPosition, cancellationToken) .GetPreviousTokenIfTouchingWord(caretPosition); return IsAfterNameColonArgument(token) || IsAfterNameEqualsArgument(token); }
public async Task<IList<string>> GetProximityExpressionsAsync( Document document, int position, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); return Do(tree, position, cancellationToken); }
public override async Task<string> GetHelpTermAsync(Document document, TextSpan span, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); // For now, find the token under the start of the selection. var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = syntaxTree.GetTouchingToken(span.Start, cancellationToken, findInsideTrivia: true); if (IsValid(token, span)) { var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var result = TryGetText(token, semanticModel, document, cancellationToken, syntaxFacts); if (string.IsNullOrEmpty(result)) { var previousToken = token.GetPreviousToken(); if (IsValid(previousToken, span)) { result = TryGetText(previousToken, semanticModel, document, cancellationToken, syntaxFacts); } } return result; } var trivia = root.FindTrivia(span.Start, findInsideTrivia: true); if (trivia.Span.IntersectsWith(span) && trivia.Kind() == SyntaxKind.PreprocessingMessageTrivia && trivia.Token.GetAncestor<RegionDirectiveTriviaSyntax>() != null) { return "#region"; } if (trivia.IsRegularOrDocComment()) { // just find the first "word" that intersects with our position var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); int start = span.Start; int end = span.Start; while (start > 0 && syntaxFacts.IsIdentifierPartCharacter(text[start - 1])) { start--; } while (end < text.Length - 1 && syntaxFacts.IsIdentifierPartCharacter(text[end])) { end++; } return text.GetSubText(TextSpan.FromBounds(start, end)).ToString(); } return string.Empty; }
private async Task<Document> ExplodePropertyAsync(SyntaxNode oldRoot, Document document, PropertyDeclarationSyntax property, CancellationToken cancellationToken) { var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // Call the Property Exploder. The code refactoring happens here. var expander = new PropertyExploder(property.Parent, property); var newRoot = expander.Visit(oldRoot); // Update code with the refactored Root return document.WithSyntaxRoot(newRoot); }
internal static async Task<DebugLocationInfo> GetInfoAsync(Document document, int position, CancellationToken cancellationToken) { // PERF: This method will be called synchronously on the UI thread for every breakpoint in the solution. // Therefore, it is important that we make this call as cheap as possible. Rather than constructing a // containing Symbol and using ToDisplayString (which might be more *correct*), we'll just do the best we // can with Syntax. This approach is capable of providing parity with the pre-Roslyn implementation. var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var syntaxFactsService = document.Project.LanguageServices.GetService<ISyntaxFactsService>(); var memberDeclaration = syntaxFactsService.GetContainingMemberDeclaration(root, position, useFullSpan: true); // It might be reasonable to return an empty Name and a LineOffset from the beginning of the // file for GlobalStatements. However, the only known caller (Breakpoints Window) doesn't // appear to consume this information, so we'll just return the simplest thing (no location). if ((memberDeclaration == null) || (memberDeclaration.Kind() == SyntaxKind.GlobalStatement)) { return default(DebugLocationInfo); } // field or event field declarations may contain multiple variable declarators. Try finding the correct one. // If the position does not point to one, try using the first one. VariableDeclaratorSyntax fieldDeclarator = null; if (memberDeclaration.Kind() == SyntaxKind.FieldDeclaration || memberDeclaration.Kind() == SyntaxKind.EventFieldDeclaration) { SeparatedSyntaxList<VariableDeclaratorSyntax> variableDeclarators = ((BaseFieldDeclarationSyntax)memberDeclaration).Declaration.Variables; foreach (var declarator in variableDeclarators) { if (declarator.FullSpan.Contains(position)) { fieldDeclarator = declarator; break; } } if (fieldDeclarator == null) { fieldDeclarator = variableDeclarators.Count > 0 ? variableDeclarators[0] : null; } } var name = syntaxFactsService.GetDisplayName(fieldDeclarator ?? memberDeclaration, DisplayNameOptions.IncludeNamespaces | DisplayNameOptions.IncludeParameters); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var lineNumber = text.Lines.GetLineFromPosition(position).LineNumber; var accessor = memberDeclaration.GetAncestorOrThis<AccessorDeclarationSyntax>(); var memberLine = text.Lines.GetLineFromPosition(accessor?.SpanStart ?? memberDeclaration.SpanStart).LineNumber; var lineOffset = lineNumber - memberLine; return new DebugLocationInfo(name, lineOffset); }
private async Task<Document> ReplaceEmptyStringWithStringEmpty(Document document, SyntaxNode oldNode, CancellationToken cancellationToken) { // NOTE: string.Empty var stringType = SF.PredefinedType(SF.Token(SyntaxKind.StringKeyword)); var empty = SF.IdentifierName("Empty"); var stringEmpty = SF.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, stringType, SF.Token(SyntaxKind.DotToken), empty); var tree = await document.GetSyntaxTreeAsync(); var node = tree.GetRoot().ReplaceNode(oldNode, stringEmpty); return document.WithSyntaxRoot(node); }
public static async Task<IEnumerable<SyntaxNode>> GetContainedSyntaxNodesAsync(Document document, CancellationToken cancellationToken) { var progressionLanguageService = document.Project.LanguageServices.GetService<IProgressionLanguageService>(); if (progressionLanguageService == null) { return SpecializedCollections.EmptyEnumerable<SyntaxNode>(); } var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); return progressionLanguageService.GetTopLevelNodesFromDocument(root, cancellationToken); }
public Document Annotate(Document document) { if (document == null) throw new ArgumentNullException("document"); _model = (SemanticModel)document.GetSemanticModelAsync().Result; var originalTree = (SyntaxTree)document.GetSyntaxTreeAsync().Result; var annotatedTree = Visit(originalTree.GetRoot()); return document.WithSyntaxRoot(annotatedTree); }
public static List<Tuple<SyntaxToken, ISymbol>> Build(Document document, TextSpan span) { var tree = (SyntaxTree)document.GetSyntaxTreeAsync(CancellationToken.None).Result; if (tree == null) { return null; } var builder = new TokenSymbolPairBuilder(document, span); builder.Visit(tree.GetRoot()); return builder.tokenSymbolPair; }
protected override async Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // first try to get the #r string literal token. If we couldn't, then we're not in a #r // reference directive and we immediately bail. SyntaxToken stringLiteral; if (!TryGetStringLiteralToken(tree, position, out stringLiteral, cancellationToken)) { return null; } var documentPath = document.Project.IsSubmission ? null : document.FilePath; var textChangeSpan = this.GetTextChangeSpan(stringLiteral, position); var gacHelper = new GlobalAssemblyCacheCompletionHelper(this, textChangeSpan, itemRules: ItemRules.Instance); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var snapshot = text.FindCorrespondingEditorTextSnapshot(); if (snapshot == null) { // Passing null to GetFileSystemDiscoveryService raises an exception. // Instead, return here since there is no longer snapshot for this document. return null; } var assemblyReferenceResolver = document.Project.CompilationOptions.MetadataReferenceResolver as AssemblyReferenceResolver; if (assemblyReferenceResolver == null) { return null; } var metadataFileResolver = assemblyReferenceResolver.PathResolver as MetadataFileReferenceResolver; if (metadataFileResolver == null) { return null; } var fileSystemHelper = new FileSystemCompletionHelper( this, textChangeSpan, GetFileSystemDiscoveryService(snapshot), Glyph.OpenFolder, Glyph.Assembly, searchPaths: metadataFileResolver.SearchPaths, allowableExtensions: new[] { ".dll", ".exe" }, exclude: path => path.Contains(","), itemRules: ItemRules.Instance); var pathThroughLastSlash = this.GetPathThroughLastSlash(stringLiteral, position); return gacHelper.GetItems(pathThroughLastSlash, documentPath).Concat( fileSystemHelper.GetItems(pathThroughLastSlash, documentPath)); }
protected override async Task<CompletionItem> GetBuilderAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken = default(CancellationToken)) { if (triggerInfo.TriggerReason == CompletionTriggerReason.TypeCharCommand) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); if (triggerInfo.IsDebugger) { // Aggressive Intellisense in the debugger: always show the builder return CreateEmptyBuilder(text, position); } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateBuilder(text, position, CSharpFeaturesResources.LambdaExpression, CSharpFeaturesResources.AutoselectDisabledDueToPotentialLambdaDeclaration); } else if (IsAnonymousObjectCreation(token)) { return CreateBuilder(text, position, CSharpFeaturesResources.MemberName, CSharpFeaturesResources.AutoselectDisabledDueToPossibleExplicitlyNamesAnonTypeMemCreation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptyBuilder(text, position); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateBuilder(text, position, CSharpFeaturesResources.ImplicitArrayCreation, CSharpFeaturesResources.AutoselectDisabledDueToPotentialImplicitArray); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateBuilder(text, position, CSharpFeaturesResources.RangeVariable, CSharpFeaturesResources.AutoselectDisabledDueToPotentialRangeVariableDecl); } } return null; }
private ImmutableArray<CodeAction> GetCodeFixes(Document document, TextSpan span, DiagnosticDescriptor descriptor) { var builder = ImmutableArray.CreateBuilder<CodeAction>(); Action<CodeAction, ImmutableArray<Diagnostic>> registerCodeFix = (a, _) => builder.Add(a); var tree = document.GetSyntaxTreeAsync(CancellationToken.None).Result; var diagnostic = Diagnostic.Create(descriptor, Location.Create(tree, span)); var context = new CodeFixContext(document, diagnostic, registerCodeFix, CancellationToken.None); var provider = CreateProvider(); provider.RegisterCodeFixesAsync(context).Wait(); return builder.ToImmutable(); }
internal static async Task<BreakpointResolutionResult> GetBreakpointAsync(Document document, int position, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (!BreakpointSpans.TryGetBreakpointSpan(tree, position, cancellationToken, out var span)) { return null; } if (span.Length == 0) { return BreakpointResolutionResult.CreateLineResult(document); } return BreakpointResolutionResult.CreateSpanResult(document, span); }
private async Task<Document> CrunchPropertyAsync(SyntaxNode oldRoot, Document document, PropertyDeclarationSyntax property, CancellationToken cancellationToken) { var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // Get the property's backing field. var backingField = property.GetBackingField(semanticModel); // Call the Property Cruncher. The code refactoring happens here. var collapser = new PropertyCruncher(semanticModel, backingField, property); var newRoot = collapser.Visit(oldRoot); // Update code with the refactored Root return document.WithSyntaxRoot(newRoot); }
public async Task AnalyzeSyntaxAsync(Document document, CancellationToken cancellationToken) { // if closed file diagnostic is off and document is not opened, then don't do anything if (!_workspace.Options.GetOption(ServiceFeatureOnOffOptions.ClosedFileDiagnostic, document.Project.Language) && !document.IsOpen()) { return; } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var diagnostics = tree.GetDiagnostics(cancellationToken); Contract.Requires(document.Project.Solution.Workspace == _workspace); var diagnosticData = diagnostics == null ? ImmutableArray<DiagnosticData>.Empty : diagnostics.Select(d => DiagnosticData.Create(document, d)).ToImmutableArrayOrEmpty(); _service.RaiseDiagnosticsUpdated(new DiagnosticsUpdatedArgs(ValueTuple.Create(this, document.Id), _workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData)); }
public static string CreateUniqueEventName( Document document, string className, string objectName, string nameOfEvent, CancellationToken cancellationToken) { var type = document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken).GetTypeByMetadataName(className); var name = objectName + "_" + nameOfEvent; var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken); var tree = document.GetSyntaxTreeAsync(cancellationToken).WaitAndGetResult(cancellationToken); var typeNode = type.DeclaringSyntaxReferences.Where(r => r.SyntaxTree == tree).Select(r => r.GetSyntax(cancellationToken)).First(); var codeModel = document.Project.LanguageServices.GetService<ICodeModelNavigationPointService>(); var point = codeModel.GetStartPoint(typeNode, EnvDTE.vsCMPart.vsCMPartBody); var reservedNames = semanticModel.LookupSymbols(point.Value.Position, type).Select(m => m.Name); return NameGenerator.EnsureUniqueness(name, reservedNames, document.Project.LanguageServices.GetService<ISyntaxFactsService>().IsCaseSensitive); }
protected override async Task<CompletionItem> GetSuggestionModeItemAsync(Document document, int position, TextSpan itemSpan, CompletionTrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) { if (trigger.Kind == CompletionTriggerKind.Insertion) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.LambdaExpression, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialLambdaDeclaration); } else if (IsAnonymousObjectCreation(token) || IsPossibleTupleExpression(token)) { return CreateSuggestionModeItem(CSharpFeaturesResources.MemberName, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPossibleExplicitlyNamesAnonTypeMemCreation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptySuggestionModeItem(itemSpan); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.ImplicitArrayCreation, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialImplicitArray); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateSuggestionModeItem(CSharpFeaturesResources.RangeVariable, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialRangeVariableDecl); } else if (tree.IsNamespaceDeclarationNameContext(position, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.NamespaceName, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToNamespaceDeclaration); } } return null; }
protected override int GetContainingClassName(Document document, SnapshotSpan fieldSpan, CancellationToken cancellationToken, ref string value, ref int hasDefaultValue) { // Find the nearest encolsing type declaration and use its name var syntaxTree = document.GetSyntaxTreeAsync(cancellationToken).WaitAndGetResult(cancellationToken); var type = syntaxTree.FindTokenOnLeftOfPosition(fieldSpan.Start.Position, cancellationToken).GetAncestor<TypeDeclarationSyntax>(); if (type != null) { value = type.Identifier.ToString(); if (!string.IsNullOrWhiteSpace(value)) { hasDefaultValue = 1; } } return VSConstants.S_OK; }
private async Task<Solution> MoveSymbolToFile(Document document, CompilationUnitSyntax syntaxRoot, TypeDeclarationSyntax typeDecl) { var identifierToken = typeDecl.Identifier; var originalSolution = document.Project.Solution; // Get the typeDecl's namespace var semanticModel = await document.GetSemanticModelAsync(); var symbol = semanticModel.GetDeclaredSymbol(typeDecl); // Build new file var newFileTree = SyntaxFactory.CompilationUnit() .WithUsings(SyntaxFactory.List(syntaxRoot.Usings)) .WithMembers( SyntaxFactory.SingletonList<MemberDeclarationSyntax>( SyntaxFactory.NamespaceDeclaration(SyntaxFactory.IdentifierName(symbol.ContainingNamespace.Name)) .WithMembers(SyntaxFactory.SingletonList<MemberDeclarationSyntax>(typeDecl)))) .WithoutLeadingTrivia() .NormalizeWhitespace(); var newDocumentId = DocumentId.CreateNewId(document.Project.Id); var newSolution = originalSolution.AddDocument(newDocumentId, identifierToken.Text, newFileTree, document.Folders); // Remove declaration from source file var syntaxTree = await document.GetSyntaxTreeAsync(); var modifiedSyntaxTree = syntaxTree.GetRoot().RemoveNode(typeDecl, SyntaxRemoveOptions.KeepNoTrivia); // If the original file now has no types, remove it completely. var remainingTypesInDocument = modifiedSyntaxTree.DescendantNodesAndSelf()? .Where(x => x.GetType() == typeof(EnumDeclarationSyntax) || x.GetType() == typeof(TypeDeclarationSyntax)).ToList(); if(remainingTypesInDocument == null || !remainingTypesInDocument.Any()) { // Remove this file completely newSolution = newSolution.RemoveDocument(document.Id); } else { // Include the modified document newSolution = newSolution.WithDocumentSyntaxRoot(document.Id, modifiedSyntaxTree); } // TOODO: Remove unused usings from both source and new. return newSolution; }
static Document ProcessCode(Document doc) { SyntaxTree tree = doc.GetSyntaxTreeAsync().Result; CompilationUnitSyntax root = (CompilationUnitSyntax) tree.GetRoot(); root = RemoveRegions(root); root = AddRequiredUsings(root); root = RemovePrivateMethods(root); root = RemovePrivateFields(root); root = DumpEvents(root); root = DumpMethods(root); root = DumpConversionOperators(root); root = DumpConstructors(root); root = DumpProperties(root); return doc.WithSyntaxRoot(root); }
private async Task <InvocationContext> GetInvocation(Microsoft.CodeAnalysis.Document document, int offset) { var sourceText = await document.GetTextAsync(); var position = offset; var tree = await document.GetSyntaxTreeAsync(); var root = await tree.GetRootAsync(); var node = root.FindToken(position).Parent; // Walk up until we find a node that we're interested in. while (node != null) { if (node is InvocationExpressionSyntax invocation && invocation.ArgumentList != null && invocation.ArgumentList.Span.Contains(position)) { var semanticModel = await document.GetSemanticModelAsync(); return(new InvocationContext(semanticModel, position, invocation.Expression, invocation.ArgumentList, invocation.IsInStaticContext())); } if (node is ObjectCreationExpressionSyntax objectCreation && objectCreation.ArgumentList != null && objectCreation.ArgumentList.Span.Contains(position)) { var semanticModel = await document.GetSemanticModelAsync(); return(new InvocationContext(semanticModel, position, objectCreation, objectCreation.ArgumentList, objectCreation.IsInStaticContext())); } if (node is AttributeSyntax attributeSyntax && attributeSyntax.ArgumentList != null && attributeSyntax.ArgumentList.Span.Contains(position)) { var semanticModel = await document.GetSemanticModelAsync(); return(new InvocationContext(semanticModel, position, attributeSyntax, attributeSyntax.ArgumentList, attributeSyntax.IsInStaticContext())); } node = node.Parent; } return(null); }
private static async Task <O.TextPart[][]> CreateDocumentLines(R.Document document, ImmutableArray <R.Diagnostic> diagnostics) { var tree = await document.GetSyntaxTreeAsync().ConfigureAwait(false); var text = await document.GetTextAsync().ConfigureAwait(false); return(text.Lines .Select(x => { // TODO: diagnostics に該当するものがないなら LinkedList 使わないで行きたい気持ち var parts = new LinkedList <WorkingTextPart>(); // TODO: シンタックスハイライト parts.AddFirst(new WorkingTextPart(O.TextPartType.Plain, x.Span, null)); foreach (var diagnostic in diagnostics) { if (diagnostic.Location.SourceTree != tree) { continue; } var diagSpan = diagnostic.Location.SourceSpan; if (!x.Span.IntersectsWith(diagSpan)) { continue; } var node = parts.First; while (node != null) { var part = node.Value; if ((!part.Severity.HasValue || part.Severity.Value < diagnostic.Severity) && part.Span.Intersection(diagSpan) is R.Text.TextSpan intersection) { if (intersection.Start > part.Span.Start) { parts.AddBefore( node, new WorkingTextPart( part.Type, new R.Text.TextSpan(part.Span.Start, intersection.Start - part.Span.Start), part.Severity ) ); } node.Value = new WorkingTextPart(part.Type, intersection, diagnostic.Severity); if (intersection.End < part.Span.End) { node = parts.AddAfter( node, new WorkingTextPart( part.Type, new R.Text.TextSpan(intersection.End, part.Span.End - intersection.End), part.Severity ) ); } } node = node.Next; } } return parts .Select(y => new O.TextPart(y.Type, text.ToString(y.Span), y.Severity)) .ToArray(); }) .ToArray()); }
/// <summary> /// Get the text changes between this document and a prior version of the same document. /// The changes, when applied to the text of the old document, will produce the text of the current document. /// </summary> public async Task <IEnumerable <TextChange> > GetTextChangesAsync(Document oldDocument, CancellationToken cancellationToken = default) { try { using (Logger.LogBlock(FunctionId.Workspace_Document_GetTextChanges, this.Name, cancellationToken)) { if (oldDocument == this) { // no changes return(SpecializedCollections.EmptyEnumerable <TextChange>()); } if (this.Id != oldDocument.Id) { throw new ArgumentException(WorkspacesResources.The_specified_document_is_not_a_version_of_this_document); } // first try to see if text already knows its changes IList <TextChange> textChanges = null; if (this.TryGetText(out var text) && oldDocument.TryGetText(out var oldText)) { if (text == oldText) { return(SpecializedCollections.EmptyEnumerable <TextChange>()); } var container = text.Container; if (container != null) { textChanges = text.GetTextChanges(oldText).ToList(); // if changes are significant (not the whole document being replaced) then use these changes if (textChanges.Count > 1 || (textChanges.Count == 1 && textChanges[0].Span != new TextSpan(0, oldText.Length))) { return(textChanges); } } } // get changes by diffing the trees if (this.SupportsSyntaxTree) { var tree = await this.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var oldTree = await oldDocument.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); return(tree.GetChanges(oldTree)); } text = await this.GetTextAsync(cancellationToken).ConfigureAwait(false); oldText = await oldDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); return(text.GetTextChanges(oldText).ToList()); } } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }