提交 722d2e08 编写于 作者: S Srivatsn Narayanan

Delete unused files in the Workspaces\Features\EditorFeatures\VS layers

上级 fbb8866b
......@@ -91,10 +91,5 @@
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
<ItemGroup>
<Compile Remove="CodeActions\GenerateVariable\GenerateVariableCodeIssueProvider.cs" />
<Compile Remove="Extensions\ClassificationExtensions.cs" />
<Compile Remove="GenerateMember\GenerateVariable\CSharpGenerateVariableService.cs" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.ComponentModel.Composition;
using System.Threading;
using Microsoft.CodeAnalysis.Compilers;
using Microsoft.CodeAnalysis.Compilers.CSharp;
using Microsoft.CodeAnalysis.CSharp.Semantics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using Microsoft.CodeAnalysis.Services.Editor.Implementation.GenerateMember.GenerateFieldOrProperty;
using Microsoft.CodeAnalysis.Services.Shared.CodeGeneration;
using Microsoft.CodeAnalysis.Services.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Utilities;
namespace Microsoft.CodeAnalysis.Services.Editor.CSharp.CodeActions.GenerateFieldOrProperty
{
[Order(Before = PredefinedCodeActionProviderNames.GenerateType)]
[ExportSyntaxNodeCodeIssueProvider(PredefinedCodeActionProviderNames.GenerateFieldOrProperty, LanguageNames.CSharp,
typeof(SimpleNameSyntax),
typeof(PropertyDeclarationSyntax))]
internal partial class GenerateFieldOrPropertyCodeIssueProvider : AbstractCSharpCodeIssueProvider
{
[ImportingConstructor]
public GenerateFieldOrPropertyCodeIssueProvider(
ILanguageServiceProviderFactory languageServiceProviderFactory,
ICodeDefinitionFactory codeDefinitionFactory)
: base(languageServiceProviderFactory, codeDefinitionFactory)
{
}
protected override CodeIssue GetIssue(
IDocument document,
SyntaxNode node,
CancellationToken cancellationToken)
{
// NOTE(DustinCa): Not supported in REPL for now.
if (document.GetSyntaxTree(cancellationToken).Options.Kind == SourceCodeKind.Interactive)
{
return null;
}
var service = document.GetLanguageService<IGenerateFieldOrPropertyService>();
var result = service.GenerateFieldOrProperty(document, node, cancellationToken);
if (!result.ContainsChanges)
{
return null;
}
return result.GetCodeIssue(cancellationToken);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.Compilers.CSharp;
using Microsoft.CodeAnalysis.CSharp.Semantics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using Microsoft.CodeAnalysis.Services.CSharp.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text.Classification;
namespace Microsoft.CodeAnalysis.Services.Editor.CSharp.Extensions
{
internal static class IClassificationTypesExtensions
{
/// <summary>
/// Determine the classification type for a given token.
/// </summary>
/// <param name="classificationTypes">A classification service to retrieve classification types.</param>
/// <param name="token">The token.</param>
/// <param name="syntaxTree">The tree containing the token (can be null for tokens that are
/// unparented).</param>
/// <returns>The correct syntactic classification for the token.</returns>
public static IClassificationType GetClassificationForToken(this IClassificationTypes classificationTypes, SyntaxToken token, SyntaxTree syntaxTree)
{
if (SyntaxFacts.IsKeywordKind(token.Kind))
{
return classificationTypes.Keyword;
}
else if (token.Kind.IsPunctuation())
{
return GetClassificationForPunctuation(classificationTypes, token);
}
else if (token.Kind == SyntaxKind.IdentifierToken)
{
return GetClassificationForIdentifer(classificationTypes, token, syntaxTree);
}
else if (token.Kind == SyntaxKind.StringLiteralToken || token.Kind == SyntaxKind.CharacterLiteralToken)
{
return token.IsVerbatimStringLiteral()
? classificationTypes.VerbatimStringLiteral
: classificationTypes.StringLiteral;
}
else if (token.Kind == SyntaxKind.NumericLiteralToken)
{
return classificationTypes.NumericLiteral;
}
return null;
}
private static IClassificationType GetClassificationForIdentifer(IClassificationTypes classificationTypes, SyntaxToken token, SyntaxTree syntaxTree)
{
if (token.Parent is TypeDeclarationSyntax &&
((token.Parent as TypeDeclarationSyntax).Identifier == token))
{
return GetClassificationForTypeDeclarationIdentifier(classificationTypes, token);
}
else if (token.Parent is EnumDeclarationSyntax &&
(token.Parent as EnumDeclarationSyntax).Identifier == token)
{
return classificationTypes.EnumTypeName;
}
else if (token.Parent is DelegateDeclarationSyntax &&
(token.Parent as DelegateDeclarationSyntax).Identifier == token)
{
return classificationTypes.DelegateTypeName;
}
else if (token.Parent is TypeParameterSyntax &&
(token.Parent as TypeParameterSyntax).Identifier == token)
{
return classificationTypes.TypeParameterName;
}
else if (syntaxTree != null && (syntaxTree.IsActualContextualKeyword(token) || syntaxTree.CouldBeVarKeywordInDeclaration(token)))
{
return classificationTypes.Keyword;
}
else
{
return classificationTypes.Identifier;
}
}
private static IClassificationType GetClassificationForTypeDeclarationIdentifier(IClassificationTypes classificationTypes, SyntaxToken identifier)
{
switch (identifier.Parent.Kind)
{
case SyntaxKind.ClassDeclaration:
return classificationTypes.TypeName;
case SyntaxKind.StructDeclaration:
return classificationTypes.StructureTypeName;
case SyntaxKind.InterfaceDeclaration:
return classificationTypes.InterfaceTypeName;
default:
return null;
}
}
private static IClassificationType GetClassificationForPunctuation(IClassificationTypes classificationTypes, SyntaxToken token)
{
if (token.Kind.IsOperator())
{
// special cases...
switch (token.Kind)
{
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
// the < and > tokens of a type parameter list should be classified as
// punctuation; otherwise, they're operators.
if (token.Parent != null)
{
if (token.Parent.Kind == SyntaxKind.TypeParameterList ||
token.Parent.Kind == SyntaxKind.TypeArgumentList)
{
return classificationTypes.Punctuation;
}
}
break;
case SyntaxKind.ColonToken:
// the : for inheritance/implements or labels should be classified as
// punctuation; otherwise, it's from a conditional operator.
if (token.Parent != null)
{
if (token.Parent.Kind != SyntaxKind.ConditionalExpression)
{
return classificationTypes.Punctuation;
}
}
break;
}
return classificationTypes.Operator;
}
else
{
return classificationTypes.Punctuation;
}
}
private static bool IsOperator(this SyntaxKind kind)
{
switch (kind)
{
case SyntaxKind.TildeToken:
case SyntaxKind.ExclamationToken:
case SyntaxKind.PercentToken:
case SyntaxKind.CaretToken:
case SyntaxKind.AmpersandToken:
case SyntaxKind.AsteriskToken:
case SyntaxKind.MinusToken:
case SyntaxKind.PlusToken:
case SyntaxKind.EqualsToken:
case SyntaxKind.BarToken:
case SyntaxKind.ColonToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.DotToken:
case SyntaxKind.QuestionToken:
case SyntaxKind.SlashToken:
case SyntaxKind.BarBarToken:
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.MinusMinusToken:
case SyntaxKind.PlusPlusToken:
case SyntaxKind.ColonColonToken:
case SyntaxKind.QuestionQuestionToken:
case SyntaxKind.MinusGreaterThanToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.EqualsGreaterThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.LessThanLessThanEqualsToken:
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.SlashEqualsToken:
case SyntaxKind.AsteriskEqualsToken:
case SyntaxKind.BarEqualsToken:
case SyntaxKind.AmpersandEqualsToken:
case SyntaxKind.PlusEqualsToken:
case SyntaxKind.MinusEqualsToken:
case SyntaxKind.CaretEqualsToken:
case SyntaxKind.PercentEqualsToken:
return true;
default:
return false;
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.ComponentModel.Composition;
using System.Threading;
using Microsoft.CodeAnalysis.Compilers;
using Microsoft.CodeAnalysis.Compilers.Common;
using Microsoft.CodeAnalysis.Compilers.CSharp;
using Microsoft.CodeAnalysis.CSharp.Semantics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using Microsoft.CodeAnalysis.Services.CSharp.Extensions;
using Microsoft.CodeAnalysis.Services.Editor.Implementation.GenerateMember.GenerateFieldOrProperty;
using Microsoft.CodeAnalysis.Services.Shared.CodeGeneration;
using Microsoft.CodeAnalysis.Services.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Services.Editor.CSharp.GenerateMember.GenerateFieldOrProperty
{
[ExportLanguageService(typeof(IGenerateFieldOrPropertyService), LanguageNames.CSharp)]
internal partial class CSharpGenerateFieldOrPropertyService :
AbstractGenerateFieldOrPropertyService<CSharpGenerateFieldOrPropertyService, SimpleNameSyntax, ExpressionSyntax>
{
[ImportingConstructor]
public CSharpGenerateFieldOrPropertyService(
ILanguageServiceProviderFactory languageServiceProviderFactory,
ICodeDefinitionFactory codeDefinitionFactory)
: base(languageServiceProviderFactory, codeDefinitionFactory)
{
}
protected override bool IsExplicitInterfaceGeneration(CommonSyntaxNode node)
{
return node is PropertyDeclarationSyntax;
}
protected override bool IsIdentifierNameGeneration(CommonSyntaxNode node)
{
return node is IdentifierNameSyntax;
}
protected override bool TryInitializeExplicitInterfaceState(
IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken,
out CommonSyntaxToken identifierToken, out IPropertySymbol propertySymbol, out INamedTypeSymbol typeToGenerateIn)
{
var propertyDeclaration = (PropertyDeclarationSyntax)node;
identifierToken = propertyDeclaration.Identifier;
if (propertyDeclaration.ExplicitInterfaceSpecifier != null)
{
var semanticModel = document.GetSemanticModel(cancellationToken);
propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken) as IPropertySymbol;
if (propertySymbol != null && !propertySymbol.ExplicitInterfaceImplementations.Any())
{
var info = semanticModel.GetTypeInfo(propertyDeclaration.ExplicitInterfaceSpecifier.Name, cancellationToken);
typeToGenerateIn = info.Type as INamedTypeSymbol;
return typeToGenerateIn != null;
}
}
identifierToken = default(CommonSyntaxToken);
propertySymbol = null;
typeToGenerateIn = null;
return false;
}
protected override bool TryInitializeIdentifierNameState(
IDocument document, SimpleNameSyntax identifierName, CancellationToken cancellationToken,
out CommonSyntaxToken identifierToken, out ExpressionSyntax simpleNameOrMemberAccessExpression)
{
identifierToken = identifierName.Identifier;
if (identifierToken.ValueText != string.Empty &&
!identifierName.IsVar)
{
var memberAccess = identifierName.Parent as MemberAccessExpressionSyntax;
simpleNameOrMemberAccessExpression = memberAccess != null && memberAccess.Name == identifierName
? (ExpressionSyntax)memberAccess
: identifierName;
// If we're being invoked, then don't offer this, offer generate method instead.
// Note: we could offer to generate a field with a delegate type. However, that's
// very esoteric and probably not what most users want.
if (!IsLegal(simpleNameOrMemberAccessExpression))
{
return false;
}
#if false
if (simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) ||
simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.ObjectCreationExpression) ||
simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.GotoStatement) ||
simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.AliasQualifiedName) ||
simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.NameColon) ||
simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.QualifiedName) ||
simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.IncompleteMember) ||
identifierName.getan.IsParentKind(SyntaxKind.UsingDirective))
{
return false;
}
#endif
return true;
}
identifierToken = default(CommonSyntaxToken);
simpleNameOrMemberAccessExpression = null;
return false;
}
private bool IsLegal(ExpressionSyntax expression)
{
if (expression.IsParentKind(SyntaxKind.ExpressionStatement) ||
(expression.IsParentKind(SyntaxKind.NameEquals) && expression.Parent.IsParentKind(SyntaxKind.AttributeArgument)) ||
expression.IsLeftSideOfAnyAssignExpression() ||
expression.IsParentKind(SyntaxKind.EqualsValueClause) ||
expression.IsParentKind(SyntaxKind.Argument) ||
expression.IsParentKind(SyntaxKind.AnonymousObjectMemberDeclarator) ||
expression.Parent is PrefixUnaryExpressionSyntax ||
expression.Parent is PostfixUnaryExpressionSyntax ||
expression.Parent is BinaryExpressionSyntax ||
expression.Parent is AssignmentExpressionSyntax ||
expression.CheckParent<ForEachStatementSyntax>(f => f.Expression == expression) ||
expression.CheckParent<MemberAccessExpressionSyntax>(m => m.Expression == expression) ||
expression.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression) ||
expression.IsParentKind(SyntaxKind.SimpleLambdaExpression))
{
return true;
}
return false;
}
}
}
......@@ -167,11 +167,5 @@
<ItemGroup>
<Folder Include="Extensibility\Navigation\" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Implementation\CodeRefactorings\CodeFix.cs" />
<Compile Remove="Implementation\CodeRefactorings\CodeRefactoringProducer.cs" />
<Compile Remove="Shared\Utilities\TextViewVisibleSpanTracker.cs" />
<Compile Remove="Shared\Utilities\VisibleSpansChangedEventArgs.cs" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CodeFixes
{
public class CodeFix
{
public CodeFixProvider Provider { get; private set; }
public TextSpan TextSpan { get; private set; }
public IEnumerable<ICodeAction> Actions { get; private set; }
public CodeFix(CodeFixProvider provider, TextSpan span, IEnumerable<ICodeAction> codeActions)
{
this.Provider = provider;
this.TextSpan = span;
this.Actions = codeActions;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.CodeAnalysis.Extensions;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeRefactorings
{
[Export(typeof(ICodeRefactoringProducer))]
internal class CodeRefactoringProducer : ICodeRefactoringProducer
{
[ImportingConstructor]
public CodeRefactoringProducer()
{
}
private IEnumerable<CodeRefactoringProvider> GetProviders(Document document)
{
return CodeRefactoringService.GetDefaultCodeRefactoringProviders(document);
}
public async Task<IEnumerable<CodeRefactoring>> GetCodeRefactoringsAsync(
Document document,
TextSpan state,
CancellationToken cancellationToken)
{
var optionService = WorkspaceServices.WorkspaceService.GetService<IOptionService>(document.Project.Solution.Workspace);
if (!optionService.GetOption(EditorComponentOnOffOptions.CodeRefactorings))
{
return SpecializedCollections.EmptyEnumerable<CodeRefactoring>();
}
using (Logger.LogBlock(FeatureId.CodeActions, FunctionId.CodeActions_RefactoringProducer_AddNewItemsWorker, cancellationToken))
{
var extensionManager = document.GetExtensionManager();
var tasks = new List<Task<CodeRefactoring>>();
var context = new CodeRefactoringContext(document, state, cancellationToken);
foreach (var provider in this.GetProviders(document))
{
tasks.Add(Task.Run(() => GetRefactoringFromProvider(
provider,
extensionManager,
context)));
}
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
return results.WhereNotNull();
}
}
private async Task<CodeRefactoring> GetRefactoringFromProvider(
CodeRefactoringProvider provider,
IExtensionManager extensionManager,
CodeRefactoringContext context)
{
context.CancellationToken.ThrowIfCancellationRequested();
if (extensionManager.IsDisabled(provider))
{
return null;
}
try
{
var actions = await provider.GetRefactoringsAsync(context).ConfigureAwait(false);
if (actions != null && actions.Count() > 0)
{
return new CodeRefactoring(provider, actions);
}
}
catch (OperationCanceledException)
{
// We don't want to catch operation canceled exceptions in the catch block
// below. So catch is here and rethrow it.
throw;
}
catch (Exception e)
{
extensionManager.HandleException(provider, e);
}
return null;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
namespace Microsoft.CodeAnalysis.Services.Editor.Shared.Utilities
{
[ExcludeFromCodeCoverage]
internal class TextViewVisibleSpanTracker
{
private readonly ITextView textView;
private readonly int initialThreadId;
private Dictionary<ITextBuffer, NormalizedSnapshotSpanCollection> bufferToPreviousVisibleSpans = new Dictionary<ITextBuffer, NormalizedSnapshotSpanCollection>();
public event EventHandler<VisibleSpansChangedEventArgs> VisibleSpansChanged;
[Obsolete("This method is currently unused and excluded from code coverage. Should you decide to use it, please add a test.")]
public TextViewVisibleSpanTracker(ITextView textView)
{
this.textView = textView;
this.textView.LayoutChanged += OnTextViewLayoutChanged;
this.textView.Closed += OnTextViewClosed;
this.initialThreadId = Thread.CurrentThread.ManagedThreadId;
}
public void RegisterSubjectBuffer(ITextBuffer subjectBuffer)
{
CheckThread();
if (!bufferToPreviousVisibleSpans.ContainsKey(subjectBuffer))
{
this.bufferToPreviousVisibleSpans.Add(subjectBuffer, ComputePossiblyVisibleSnapshotSpans(textView, subjectBuffer.CurrentSnapshot));
}
}
private void OnTextViewClosed(object sender, EventArgs e)
{
CheckThread();
this.textView.LayoutChanged -= OnTextViewLayoutChanged;
this.textView.Closed -= this.OnTextViewClosed;
}
private void OnTextViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
{
CheckThread();
var bufferToPreviousVisibleSpansLocal = this.bufferToPreviousVisibleSpans;
var bufferToCurrentVisibleSpansLocal = new Dictionary<ITextBuffer, NormalizedSnapshotSpanCollection>(bufferToPreviousVisibleSpansLocal.Count);
foreach (var subjectBuffer in bufferToPreviousVisibleSpansLocal.Keys)
{
bufferToCurrentVisibleSpansLocal.Add(subjectBuffer, ComputePossiblyVisibleSnapshotSpans(textView, subjectBuffer.CurrentSnapshot));
}
this.bufferToPreviousVisibleSpans = bufferToCurrentVisibleSpansLocal;
var visibleSpansChanged = VisibleSpansChanged;
if (visibleSpansChanged == null)
{
return;
}
foreach (var subjectBuffer in bufferToCurrentVisibleSpansLocal.Keys)
{
var previous = bufferToPreviousVisibleSpansLocal[subjectBuffer];
var current = bufferToCurrentVisibleSpansLocal[subjectBuffer];
if (previous != current)
{
#pragma warning disable 618
visibleSpansChanged(this, new VisibleSpansChangedEventArgs(subjectBuffer, current));
#pragma warning restore 618
}
}
}
public NormalizedSnapshotSpanCollection GetPossiblyVisibleSnapshotSpans(ITextSnapshot snapshot)
{
CheckThread();
#pragma warning disable 618
RegisterSubjectBuffer(snapshot.TextBuffer);
#pragma warning restore 618
var spans = bufferToPreviousVisibleSpans[snapshot.TextBuffer];
Debug.Assert(!spans.Any() || spans.First().Snapshot == snapshot, "We don't have visible spans for this solution");
return spans;
}
[Conditional("DEBUG")]
private void CheckThread()
{
Debug.Assert(this.initialThreadId == Thread.CurrentThread.ManagedThreadId);
}
/// <summary>
/// Returns a set of all visible spans and potentially some invisible ones.
/// In a common scenario of view snapshot matching text snapshot with limited amount of hidden text
/// getting "potential" visible spans could be acceptable cheaper alternative to the more precise GetVisibleSnapshotSpans.
/// </summary>
private static NormalizedSnapshotSpanCollection ComputePossiblyVisibleSnapshotSpans(ITextView textView, ITextSnapshot snapshot)
{
Debug.Assert(!textView.IsClosed);
// We may get asked to start tracking a view before any layout has happened.
if (textView.TextViewLines == null)
{
return new NormalizedSnapshotSpanCollection();
}
// MapUpTo/DownTo are expensive functions involving multiple allocations, so we are
// trying to catch the common case here - the view snapshot is the same as the given
// snapshot && if there is some hidden text it is not too large compared to the visual
// size so precise filtering of visible from not visible may not worth the effort.
var formattedSpan = textView.TextViewLines.FormattedSpan;
var formattedLength = formattedSpan.Length;
var visualLength = textView.VisualSnapshot.Length;
// TODO: heuristic of what is considered "too much" for potentially invisible text could be tuned further
// Here we do a simple comparison "text with possibly hidden parts" <= "visible text * 2"
// For the most part we just need to prevent extreme cases - when collapsed text contains pages and pages of text.
if (formattedSpan.Snapshot == snapshot && (formattedLength / 2 <= visualLength))
{
return new NormalizedSnapshotSpanCollection(formattedSpan);
}
return ComputeVisibleSnapshotSpans(textView, snapshot);
}
private static NormalizedSnapshotSpanCollection ComputeVisibleSnapshotSpans(ITextView textView, ITextSnapshot snapshot)
{
// We don't want to just return this.TextView.TextViewLines.FormattedSpan. This is
// because the formatted span may be huge (in the case of collapsed outlining regions).
// So we instead only pick the lines that are in some way visible on the screen.
// but we let the editor do the heavy lifting for us - we just map the FormattedSpan up to the visual snapshot,
// then map that back down which gives us a set of spans that contains only the visible stuff.
var bufferGraph = textView.BufferGraph;
var visualSnapshot = textView.VisualSnapshot;
var visualSpans = bufferGraph.MapUpToSnapshot(textView.TextViewLines.FormattedSpan, SpanTrackingMode.EdgeExclusive, visualSnapshot);
Debug.Assert(visualSpans.Count == 1, "More than one visual span?");
var spans = bufferGraph.MapDownToSnapshot(visualSpans.Single(), SpanTrackingMode.EdgeExclusive, snapshot);
return spans;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
namespace Microsoft.CodeAnalysis.Services.Editor.Shared.Utilities
{
[ExcludeFromCodeCoverage]
internal class VisibleSpansChangedEventArgs : EventArgs
{
public ITextBuffer TextBuffer { get; private set; }
public NormalizedSnapshotSpanCollection VisibleSpans { get; private set; }
[Obsolete("This method is currently unused and excluded from code coverage. Should you decide to use it, please add a test.")]
public VisibleSpansChangedEventArgs(ITextBuffer textBuffer, NormalizedSnapshotSpanCollection visibleSpans)
{
this.TextBuffer = textBuffer;
this.VisibleSpans = visibleSpans;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Shared.Tagging;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Tagging;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics
{
public class DiagnosticTagSourceTests
{
[WpfFact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
public void Test_TagSourceDiffer()
{
using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromFiles(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default))
{
var registrationService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>();
registrationService.Register(workspace);
var analyzer = new Analyzer();
var analyzerService = new TestDiagnosticAnalyzerService(
new Dictionary<string, ImmutableArray<DiagnosticAnalyzer>>() { { LanguageNames.CSharp, ImmutableArray.Create<DiagnosticAnalyzer>(analyzer) } }.ToImmutableDictionary());
var listener = new AsynchronousOperationListener();
var listeners = AsynchronousOperationListener.CreateListeners(
ValueTuple.Create(FeatureAttribute.DiagnosticService, listener),
ValueTuple.Create(FeatureAttribute.ErrorSquiggles, listener));
var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(analyzerService), listeners);
var provider = new DiagnosticsSquiggleTaggerProvider(
workspace.Services.GetService<IOptionService>(), diagnosticService,
workspace.GetService<IForegroundNotificationService>(), listeners);
var tagger = provider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer());
using (var disposable = tagger as IDisposable)
{
var service = workspace.Services.GetService<ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService;
var incrementalAnalyzers = ImmutableArray.Create(analyzerService.CreateIncrementalAnalyzer(workspace));
// test first update
service.WaitUntilCompletion_ForTestingPurposesOnly(workspace, incrementalAnalyzers);
listener.CreateWaitTask().PumpingWait();
var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot;
var spans = tagger.GetTags(new NormalizedSnapshotSpanCollection(new SnapshotSpan(snapshot, 0, snapshot.Length))).ToList();
Assert.True(spans.First().Span.Contains(new Span(0, 1)));
// test second update
analyzer.ChangeSeverity();
var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id);
var text = document.GetTextAsync().Result;
workspace.TryApplyChanges(document.WithText(text.WithChanges(new TextChange(new TextSpan(text.Length - 1, 1), string.Empty))).Project.Solution);
service.WaitUntilCompletion_ForTestingPurposesOnly(workspace, incrementalAnalyzers);
listener.CreateWaitTask().PumpingWait();
snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot;
spans = tagger.GetTags(new NormalizedSnapshotSpanCollection(new SnapshotSpan(snapshot, 0, snapshot.Length))).ToList();
Assert.True(spans.First().Span.Contains(new Span(0, 1)));
registrationService.Unregister(workspace);
}
}
}
private class Analyzer : DiagnosticAnalyzer
{
private DiagnosticDescriptor _rule = new DiagnosticDescriptor("test", "test", "test", "test", DiagnosticSeverity.Error, true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get
{
return ImmutableArray.Create(_rule);
}
}
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxTreeAction(c =>
{
c.ReportDiagnostic(Diagnostic.Create(_rule, Location.Create(c.Tree, new Text.TextSpan(0, 1))));
});
}
public void ChangeSeverity()
{
_rule = new DiagnosticDescriptor("test", "test", "test", "test", DiagnosticSeverity.Warning, true);
}
}
}
}
......@@ -175,9 +175,5 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Diagnostics\DiagnosticTagSourceTests.cs" />
<Compile Remove="TestComposition.cs" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.WorkspaceServices;
using Roslyn.Test.Utilities;
namespace Microsoft.CodeAnalysis.Editor.UnitTests
{
[Export]
public class TestComposition
{
public readonly ComposablePartCatalog PartCatalog;
public readonly ExportProvider ExportProvider;
public readonly ComposablePartCatalog MinimumCatalog;
public TestComposition()
{
PartCatalog = GetAssemblyCatalog(GetTypes());
ExportProvider = new CompositionContainer(PartCatalog, isThreadSafe: true);
MinimumCatalog = new AggregateCatalog(new TypeCatalog(GetRoslynTypes()), GetAssemblyCatalog(GetVisualStudioTypes()));
}
private static Type[] GetRoslynTypes()
{
var types = new[]
{
// ROSLYN
typeof(Microsoft.CodeAnalysis.WorkspaceServices.WorkspaceServiceProviderFactory),
typeof(Microsoft.CodeAnalysis.LanguageServices.LanguageServiceProviderFactoryWorkspaceServiceFactory),
typeof(Microsoft.CodeAnalysis.Editor.Implementation.Workspaces.WorkspaceTaskSchedulerFactoryFactory),
typeof(Microsoft.CodeAnalysis.Host.WorkspaceTaskSchedulerFactoryFactory),
typeof(Microsoft.CodeAnalysis.Host.BackgroundCompilerFactoryFactory),
typeof(Microsoft.CodeAnalysis.Formatting.Rules.DefaultBaseIndentationFormattingRuleFactoryServiceFactory),
typeof(Microsoft.CodeAnalysis.Editor.Implementation.Workspaces.PersistenceServiceFactory),
typeof(Microsoft.CodeAnalysis.Text.Implementation.TextBufferFactoryService.TextBufferCloneServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.PersistentStorageServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.AssemblyShadowCopyProviderServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.TemporaryStorageServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.TextFactoryServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.SyntaxTreeCacheServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.TextCacheServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.CompilationCacheServiceFactory),
typeof(Microsoft.CodeAnalysis.Host.BackgroundParserFactoryFactory),
typeof(Microsoft.CodeAnalysis.CSharp.CSharpCompilationFactoryService),
typeof(Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationFactoryService),
typeof(Solution), // ServicesCore
typeof(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTreeFactoryServiceFactory), // CSharpServicesCore
typeof(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTreeFactoryServiceFactory), // BasicServicesCore
typeof(Microsoft.CodeAnalysis.CSharp.CodeActions.AbstractCSharpCodeIssueProvider), // CSharpFeatures
typeof(Microsoft.CodeAnalysis.VisualBasic.CodeActions.AbstractVisualBasicCodeIssueProvider), // BasicFeatures
typeof(Microsoft.CodeAnalysis.Options.OptionService), // Service
typeof(Microsoft.CodeAnalysis.Options.OptionsServiceFactory),
typeof(Microsoft.CodeAnalysis.Options.Providers.ExportedOptionProvider),
typeof(Microsoft.CodeAnalysis.Editor.CSharp.ContentType.ContentTypeDefinitions), // CSharp Content Type
typeof(Microsoft.CodeAnalysis.Editor.VisualBasic.ContentType.ContentTypeDefinitions), // VB Content Type
typeof(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxFactsService),
typeof(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxFactsService),
typeof(Microsoft.CodeAnalysis.Editor.Implementation.Workspaces.EditorCompletionOptionsFactoryServiceFactory),
typeof(Microsoft.CodeAnalysis.Editor.CSharp.Formatting.Indentation.SmartIndentProvider),
typeof(Microsoft.CodeAnalysis.Editor.VisualBasic.Formatting.Indentation.SmartIndentProvider),
typeof(Microsoft.CodeAnalysis.Editor.Implementation.ForegroundNotification.ForegroundNotificationService),
typeof(TestWaitIndicator),
typeof(TestExtensionErrorHandler),
typeof(IContentTypeAndTextViewRoleMetadata),
typeof(TestExportProvider),
typeof(Microsoft.CodeAnalysis.Diagnostics.CompilerDiagnosticService)
};
return types.Concat(TestHelpers.GetAllTypesImplementingGivenInterface(typeof(Microsoft.CodeAnalysis.CSharp.Formatting.DefaultOperationProvider).Assembly, typeof(IFormattingService)))
.Concat(TestHelpers.GetAllTypesImplementingGivenInterface(typeof(Microsoft.CodeAnalysis.VisualBasic.Formatting.DefaultOperationProvider).Assembly, typeof(IFormattingService)))
.Concat(TestHelpers.GetAllTypesImplementingGivenInterface(typeof(Microsoft.CodeAnalysis.CSharp.Formatting.DefaultOperationProvider).Assembly, typeof(IFormattingRule)))
.Concat(TestHelpers.GetAllTypesImplementingGivenInterface(typeof(Microsoft.CodeAnalysis.VisualBasic.Formatting.DefaultOperationProvider).Assembly, typeof(IFormattingRule)))
.Concat(TestHelpers.GetAllTypesImplementingGivenInterface(typeof(Microsoft.CodeAnalysis.CSharp.Formatting.DefaultOperationProvider).Assembly, typeof(ICodeGenerationService)))
.Concat(TestHelpers.GetAllTypesImplementingGivenInterface(typeof(Microsoft.CodeAnalysis.VisualBasic.Formatting.DefaultOperationProvider).Assembly, typeof(ICodeGenerationService)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(SolutionCrawlerOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(EditorComponentOnOffOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(ServiceComponentOnOffOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(Microsoft.CodeAnalysis.Formatting.FormattingOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Distinct()
.ToArray();
}
private static Type[] GetVisualStudioTypes()
{
var types = new[]
{
// EDITOR
// Microsoft.VisualStudio.Platform.VSEditor.dll:
typeof(Microsoft.VisualStudio.Platform.VSEditor.EventArgsHelper),
// Microsoft.VisualStudio.Text.Logic.dll:
// Must include this because several editor options are actually stored as exported information
// on this DLL. Including most importantly, the tab size information.
typeof(Microsoft.VisualStudio.Text.Editor.DefaultOptions),
// Microsoft.VisualStudio.Text.UI.dll:
// Include this DLL to get several more EditorOptions including WordWrapStyle.
typeof(Microsoft.VisualStudio.Text.Editor.WordWrapStyle),
// Microsoft.VisualStudio.Text.UI.Wpf.dll:
// Include this DLL to get more EditorOptions values.
typeof(Microsoft.VisualStudio.Text.Editor.HighlightCurrentLineOption),
// StandaloneUndo.dll:
// Include this DLL to get more undo operations.
typeof(Microsoft.VisualStudio.Text.Operations.Standalone.NullMergeUndoTransactionPolicy),
// Microsoft.VisualStudio.Language.StandardClassification.dll:
typeof(Microsoft.VisualStudio.Language.StandardClassification.PredefinedClassificationTypeNames)
};
return types;
}
private static Type[] GetTypes()
{
return GetRoslynTypes().Concat(GetVisualStudioTypes()).ToArray();
}
private static ComposablePartCatalog GetAssemblyCatalog(IEnumerable<Type> types)
{
return new AggregateCatalog(types.Select(t => t.Assembly).Distinct().Select(a => new AssemblyCatalog(a)));
}
}
}
......@@ -207,9 +207,5 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Compile Remove="SimplifyTypeNames\AbstractNameSimplificationServiceTests.vb" />
<Compile Remove="SimplifyTypeNames\NameSimplificationServiceTests.vb" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Option Strict Off
Imports System.Xml.Linq
Imports Microsoft.CodeAnalysis.Compilers
Imports Microsoft.CodeAnalysis.Services.Editor.UnitTests.Utilities
Imports Microsoft.CodeAnalysis.Services.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Services.Simplification
Imports Microsoft.CodeAnalysis.Text
Namespace Microsoft.CodeAnalysis.Services.Editor.UnitTests.CodeActions.SimplifyTypeNames
Partial Public Class AbstractNameSimplificationServiceTests
Protected Shadows Sub Test(definition As XElement, expected As String, Optional codeActionIndex As Integer = 0, Optional compareTokens As Boolean = True)
Using workspace = TestWorkspaceFactory.CreateWorkspace(definition)
Dim document = GetDocument(workspace)
Dim updatedRoot = SimplificationService.Simplify(document).GetSyntaxRoot()
Dim language As String = document.LanguageServices.Language
Dim actualText = If(compareTokens, updatedRoot.ToString(), updatedRoot.ToFullString())
If compareTokens Then
AssertEx.TokensAreEqual(expected, actualText, If(language = LanguageNames.VisualBasic, LanguageNames.CSharp, LanguageNames.VisualBasic))
Else
Assert.Equal(expected, actualText)
End If
End Using
End Sub
Protected Shared Function GetDocument(workspace As TestWorkspace) As Document
Dim buffer = workspace.Documents.First().TextBuffer
Dim document As Document = Nothing
workspace.CurrentSolution.TryGetDocumentWithSpecificText(buffer.CurrentSnapshot.AsText(), document)
Return document
End Function
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Option Strict Off
Imports Microsoft.CodeAnalysis.Compilers
Imports Microsoft.CodeAnalysis.Services.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Services.Simplification
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Namespace Microsoft.CodeAnalysis.Services.Editor.UnitTests.CodeActions.SimplifyTypeNames
Partial Public Class NameSimplificationServiceTests
Inherits AbstractNameSimplificationServiceTests
#Region "Normal CSharp Tests"
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub TestSimplifyAllNodes_UseAlias()
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
using MyType = System.Exception;
class A
{
System.Exception c;
}
</Document>
</Project>
</Workspace>
Dim expected =
<text>
using MyType = System.Exception;
class A
{
MyType c;
}
</text>.Value
Test(input, expected)
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub TestSimplifyAllNodes_TwoAliases()
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
using MyType1 = System.Exception;
namespace Root
{
using MyType2 = System.Exception;
class A
{
System.Exception c;
}
}
</Document>
</Project>
</Workspace>
Dim expected =
<text>
using MyType1 = System.Exception;
namespace Root
{
using MyType2 = MyType1;
class A
{
MyType2 c;
}
}
</text>.Value
Test(input, expected)
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub TestSimplifyAllNodes_SimplifyTypeName()
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
using System;
namespace Root
{
class A
{
System.Exception c;
}
}
</Document>
</Project>
</Workspace>
Dim expected =
<text>
using System;
namespace Root
{
class A
{
Exception c;
}
}
</text>.Value
Test(input, expected)
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub TestGetChanges_SimplifyTypeName()
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
using System;
namespace Root
{
class A
{
System.Exception c;
}
}
</Document>
</Project>
</Workspace>
Using workspace = TestWorkspaceFactory.CreateWorkspace(input)
Dim document = GetDocument(workspace)
Dim simplified = SimplificationService.Simplify(document)
Dim decl = simplified.GetSyntaxRoot().DescendantNodes().Where(Function(n) n.ToString() = "c").First().Parent
Dim type = decl.ChildNodesAndTokens(0)
Assert.Equal("Exception", type.ToString())
End Using
End Sub
#End Region
#Region "Normal Visual Basic Tests"
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub VisualBasic_TestSimplifyAllNodes_UseAlias()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Imports Ex = System.Exception
Class A
Public e As System.Exception
End Class
</Document>
</Project>
</Workspace>
Dim expected =
<text>
Imports Ex = System.Exception
Class A
Public e As Ex
End Class
</text>.Value
Test(input, expected)
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub VisualBasic_TestSimplifyAllNodes_SimplifyTypeName()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Imports System
Namespace Root
Class A
Private e As System.Exception
End Class
End Namespace
</Document>
</Project>
</Workspace>
Dim expected =
<text>
Imports System
Namespace Root
Class A
Private e As Exception
End Class
End Namespace
</text>.Value
Test(input, expected)
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub VisualBasic_TestGetChanges_SimplifyTypeName()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Imports Ex = System.Exception
Namespace Root
Class A
Private e As System.Exception
End Class
End Namespace
</Document>
</Project>
</Workspace>
Using workspace = TestWorkspaceFactory.CreateWorkspace(input)
Dim document = GetDocument(workspace)
Dim changes = SimplificationService.Simplify(document).GetTextChanges(document)
Assert.Equal("Ex", changes.FirstOrDefault().NewText)
Assert.Equal(TextSpan.FromBounds(163, 179), changes.FirstOrDefault().Span)
End Using
End Sub
<WorkItem(547117, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547117")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub VisualBasic_TestGetChanges_SimplifyTypeName_Array_1()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Module Program
Dim Foo() As Integer
Sub Main(args As String())
Program.Foo(23) = 23
End Sub
End Module
</Document>
</Project>
</Workspace>
Dim expected =
<text>
Module Program
Dim Foo() As Integer
Sub Main(args As String())
Foo(23) = 23
End Sub
End Module
</text>.Value
Test(input, expected)
End Sub
<WorkItem(547117, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547117")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)>
Public Sub VisualBasic_TestGetChanges_SimplifyTypeName_Array_2()
Dim input =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Module Program
Dim Bar() As Action(Of Integer)
Sub Main(args As String())
Program.Bar(2)(2)
End Sub
End Module
</Document>
</Project>
</Workspace>
Dim expected =
<text>
Module Program
Dim Bar() As Action(Of Integer)
Sub Main(args As String())
Bar(2)(2)
End Sub
End Module
</text>.Value
Test(input, expected)
End Sub
#End Region
End Class
End Namespace
......@@ -96,9 +96,5 @@
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Extensions\ClassificationExtensions.vb" />
<Compile Remove="GenerateMember\GenerateVariable\VisualBasicGenerateVariableService.vb" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Runtime.CompilerServices
Imports Microsoft.CodeAnalysis.Compilers.VisualBasic
Imports Microsoft.CodeAnalysis.Services.Editor.Implementation.ExtractMethod
Imports Microsoft.CodeAnalysis.Services.Editor.VisualBasic.Utilities
Imports Microsoft.CodeAnalysis.Services.VisualBasic.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.VisualStudio.Text.Classification
Namespace Microsoft.CodeAnalysis.Services.Editor.VisualBasic.Extensions
<Extension()>
Friend Module IClassificationTypesExtensions
''' <summary>
''' Return the classification type associated with this token.
''' </summary>
''' <param name="classificationTypes">The source of classification types.</param>
''' <param name="token">The token to be classified.</param>
''' <returns>The classification type for the token</returns>
''' <remarks></remarks>
<Extension()>
Public Function GetClassificationForToken(classificationTypes As IClassificationTypes, token As SyntaxToken) As IClassificationType
If token.Kind.IsKeywordKind() Then
Return classificationTypes.Keyword
ElseIf token.Kind.IsPunctuation() Then
Return ClassifyPunctuation(classificationTypes, token)
ElseIf token.Kind = SyntaxKind.IdentifierToken Then
Return ClassifyIdentifierSyntax(classificationTypes, token)
ElseIf token.MatchesKind(SyntaxKind.StringLiteralToken, SyntaxKind.CharacterLiteralToken) Then
Return classificationTypes.StringLiteral
ElseIf token.MatchesKind(
SyntaxKind.DecimalLiteralToken,
SyntaxKind.FloatingLiteralToken,
SyntaxKind.IntegerLiteralToken,
SyntaxKind.DateLiteralToken) Then
Return classificationTypes.NumericLiteral
ElseIf token.Kind = SyntaxKind.XmlNameToken Then
Return classificationTypes.XmlName
ElseIf token.Kind = SyntaxKind.XmlTextLiteralToken Then
Select Case token.Parent.Kind
Case SyntaxKind.XmlString
Return classificationTypes.XmlAttributeValue
Case SyntaxKind.XmlProcessingInstruction
Return classificationTypes.XmlProcessingInstruction
Case SyntaxKind.XmlComment
Return classificationTypes.XmlComment
Case SyntaxKind.XmlCDataSection
Return classificationTypes.XmlCDataSection
Case Else
Return classificationTypes.XmlText
End Select
ElseIf token.Kind = SyntaxKind.XmlEntityLiteralToken Then
Return classificationTypes.XmlEntityReference
ElseIf token.MatchesKind(SyntaxKind.None, SyntaxKind.BadToken) Then
Return Nothing
Else
Return Contract.FailWithReturn(Of IClassificationType)("Unhandled token kind: " & token.Kind)
End If
End Function
Private Function ClassifyPunctuation(classificationTypes As IClassificationTypes, token As SyntaxToken) As IClassificationType
If AllOperators.Contains(token.Kind) Then
' special cases...
Select Case token.Kind
Case SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken
If TypeOf token.Parent Is AttributeBlockSyntax Then
Return classificationTypes.Punctuation
End If
End Select
Return classificationTypes.Operator
Else
Return classificationTypes.Punctuation
End If
End Function
Private Function ClassifyIdentifierSyntax(classificationTypes As IClassificationTypes, identifier As SyntaxToken) As IClassificationType
'Note: parent might be Nothing, if we are classifying raw tokens.
Dim parent = identifier.Parent
If TypeOf parent Is TypeStatementSyntax AndAlso
DirectCast(parent, TypeStatementSyntax).Identifier = identifier Then
Return ClassifyTypeDeclarationIdentifier(classificationTypes, identifier)
ElseIf TypeOf parent Is EnumStatementSyntax AndAlso
DirectCast(parent, EnumStatementSyntax).Identifier = identifier Then
Return classificationTypes.EnumTypeName
ElseIf TypeOf parent Is DelegateStatementSyntax AndAlso
DirectCast(parent, DelegateStatementSyntax).Identifier = identifier AndAlso
(parent.Kind = SyntaxKind.DelegateSubStatement OrElse
parent.Kind = SyntaxKind.DelegateFunctionStatement) Then
Return classificationTypes.DelegateTypeName
ElseIf TypeOf parent Is TypeParameterSyntax AndAlso
DirectCast(parent, TypeParameterSyntax).Identifier = identifier Then
Return classificationTypes.TypeParameterName
ElseIf (identifier.GetText() = "IsTrue" OrElse identifier.GetText() = "IsFalse") AndAlso
TypeOf parent Is OperatorStatementSyntax AndAlso
DirectCast(parent, OperatorStatementSyntax).Operator = identifier Then
Return classificationTypes.Keyword
Else
Return classificationTypes.Identifier
End If
End Function
Private Function ClassifyTypeDeclarationIdentifier(classificationTypes As IClassificationTypes, identifier As SyntaxToken) As IClassificationType
Select Case identifier.Parent.Kind
Case SyntaxKind.ClassStatement
Return classificationTypes.TypeName
Case SyntaxKind.ModuleStatement
Return classificationTypes.ModuleTypeName
Case SyntaxKind.InterfaceStatement
Return classificationTypes.InterfaceTypeName
Case SyntaxKind.StructureStatement
Return classificationTypes.StructureTypeName
Case Else
Return Contract.FailWithReturn(Of IClassificationType)("Unhandled type declaration")
End Select
End Function
End Module
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.ComponentModel.Composition
Imports System.Threading
Imports Microsoft.CodeAnalysis.Compilers
Imports Microsoft.CodeAnalysis.Compilers.Common
Imports Microsoft.CodeAnalysis.Compilers.VisualBasic
Imports Microsoft.CodeAnalysis.Services.Editor.Implementation.GenerateMember.GenerateFieldOrProperty
Imports Microsoft.CodeAnalysis.Services.Editor.VisualBasic.Extensions
Imports Microsoft.CodeAnalysis.Services.Shared.CodeGeneration
Imports Microsoft.CodeAnalysis.Services.VisualBasic.Extensions
Imports Microsoft.CodeAnalysis.Services.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.Text
Namespace Microsoft.CodeAnalysis.Services.Editor.VisualBasic.GenerateMember.GenerateFieldOrProperty
<ExportLanguageService(GetType(IGenerateFieldOrPropertyService), LanguageNames.VisualBasic)>
Partial Friend Class VisualBasicGenerateFieldOrPropertyService
Inherits AbstractGenerateFieldOrPropertyService(Of VisualBasicGenerateFieldOrPropertyService, SimpleNameSyntax, ExpressionSyntax)
<ImportingConstructor()>
Public Sub New(
languageServiceProviderFactory As ILanguageServiceProviderFactory,
codeDefinitionFactory As ICodeDefinitionFactory)
MyBase.New(languageServiceProviderFactory, codeDefinitionFactory)
End Sub
Protected Overrides Function IsExplicitInterfaceGeneration(node As Microsoft.CodeAnalysis.Common.CommonSyntaxNode) As Boolean
Return TypeOf node Is QualifiedNameSyntax
End Function
Protected Overrides Function IsIdentifierNameGeneration(node As Microsoft.CodeAnalysis.Common.CommonSyntaxNode) As Boolean
Return TypeOf node Is IdentifierNameSyntax
End Function
Protected Overrides Function TryInitializeExplicitInterfaceState(
document As IDocument, node As CommonSyntaxNode, cancellationToken As CancellationToken,
ByRef identifierToken As CommonSyntaxToken, ByRef propertySymbol As IPropertySymbol, ByRef typeToGenerateIn As INamedTypeSymbol) As Boolean
Dim qualifiedName = DirectCast(node, QualifiedNameSyntax)
identifierToken = qualifiedName.Right.Identifier
If qualifiedName.IsParentKind(SyntaxKind.ImplementsClause) Then
Dim implementsClause = DirectCast(qualifiedName.Parent, ImplementsClauseSyntax)
If implementsClause.IsParentKind(SyntaxKind.PropertyStatement) OrElse
implementsClause.IsParentKind(SyntaxKind.PropertyBlock) Then
Dim propertyBlock = TryCast(implementsClause.Parent, PropertyBlockSyntax)
Dim propertyNode = If(implementsClause.IsParentKind(SyntaxKind.PropertyStatement),
DirectCast(implementsClause.Parent, PropertyStatementSyntax),
propertyBlock.Begin)
Dim semanticModel = document.GetSemanticModel(cancellationToken)
propertySymbol = DirectCast(semanticModel.GetDeclaredSymbol(propertyNode, cancellationToken), IPropertySymbol)
If propertySymbol IsNot Nothing AndAlso Not propertySymbol.ExplicitInterfaceImplementations.Any() Then
Dim info = semanticModel.GetTypeInfo(qualifiedName.Left, cancellationToken)
typeToGenerateIn = TryCast(info.Type, INamedTypeSymbol)
Return typeToGenerateIn IsNot Nothing
End If
End If
End If
identifierToken = Nothing
propertySymbol = Nothing
typeToGenerateIn = Nothing
Return False
End Function
Protected Overrides Function TryInitializeIdentifierNameState(
document As IDocument, identifierName As SimpleNameSyntax, cancellationToken As CancellationToken,
ByRef identifierToken As CommonSyntaxToken, ByRef simpleNameOrMemberAccessExpression As ExpressionSyntax) As Boolean
identifierToken = identifierName.Identifier
Dim memberAccess = TryCast(identifierName.Parent, MemberAccessExpressionSyntax)
simpleNameOrMemberAccessExpression =
If(memberAccess IsNot Nothing AndAlso memberAccess.Name Is identifierName,
DirectCast(memberAccess, ExpressionSyntax),
identifierName)
If Not simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) AndAlso
Not simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.ObjectCreationExpression) AndAlso
Not simpleNameOrMemberAccessExpression.IsParentKind(SyntaxKind.AddressOfExpression) Then
Dim syntaxTree = document.GetVisualBasicSyntaxTree(cancellationToken)
If syntaxTree.IsExpressionContext(simpleNameOrMemberAccessExpression.Span.Start) OrElse
syntaxTree.IsSingleLineStatementContext(simpleNameOrMemberAccessExpression.Span.Start) Then
Return True
End If
End If
identifierToken = Nothing
simpleNameOrMemberAccessExpression = Nothing
Return False
End Function
End Class
End Namespace
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.AddImport;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.AddImport
{
[ExportDiagnosticProvider(PredefinedDiagnosticProviderNames.AddUsingOrImport, LanguageNames.CSharp)]
internal sealed class CSharpAddImportDiagnosticProvider : AbstractAddImportDiagnosticProvider<SimpleNameSyntax, QualifiedNameSyntax, IncompleteMemberSyntax, BlockSyntax, EqualsValueClauseSyntax>
{
}
}
......@@ -76,13 +76,6 @@
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="$(SystemValueTupleVersion)" />
</ItemGroup>
<ItemGroup>
<Compile Remove="AddImport\CSharpAddImportDiagnosticProvider.cs" />
<Compile Remove="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastDiagnosticProvider.cs" />
<Compile Remove="CodeFixes\SimplifyTypeNames\SimplifyTypeNamesDiagnosticProvider.cs" />
<Compile Remove="CodeRefactorings\CSharpCodeRefactoringService.cs" />
<Compile Remove="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="..\..\..\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.RemoveUnnecessaryCast
{
[ExportDiagnosticProvider(PredefinedDiagnosticProviderNames.RemoveUnnecessaryCast, LanguageNames.CSharp)]
internal sealed class RemoveUnnecessaryCastDiagnosticProvider : ScopedDiagnosticProvider
{
internal const string DiagnosticId = "RemoveUnnecessaryCast";
internal static readonly DiagnosticDescriptor DiagnosticMD = new DiagnosticDescriptor(DiagnosticId,
DiagnosticKind.Unnecessary,
CSharpFeaturesResources.Remove_Unnecessary_Cast,
CSharpFeaturesResources.Cast_is_redundant,
"Internal",
DiagnosticSeverity.None);
public override IEnumerable<DiagnosticDescriptor> GetSupportedDiagnostics()
{
return SpecializedCollections.SingletonEnumerable(DiagnosticMD);
}
protected override async Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(Document document, TextSpan span, CancellationToken cancellationToken)
{
if (!document.IsOpen())
{
return null;
}
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var node = root.FindNode(span);
List<Diagnostic> result = null;
if (node.IsKind(SyntaxKind.CompilationUnit))
{
var compilationUnit = (CompilationUnitSyntax)node;
result = ProcessNodes(model, compilationUnit.AttributeLists, result, cancellationToken);
result = ProcessNodes(model, compilationUnit.Members, result, cancellationToken);
}
else
{
result = ProcessNode(model, node, result, cancellationToken);
}
return result;
}
private List<Diagnostic> ProcessNodes<T>(
SemanticModel model, IEnumerable<T> nodes, List<Diagnostic> result, CancellationToken cancellationToken) where T : SyntaxNode
{
foreach (var node in nodes)
{
result = ProcessNode(model, node, result, cancellationToken);
}
return result;
}
private List<Diagnostic> ProcessNode(SemanticModel model, SyntaxNode node, List<Diagnostic> result, CancellationToken cancellationToken)
{
foreach (var cast in node.DescendantNodesAndSelf().OfType<CastExpressionSyntax>())
{
cancellationToken.ThrowIfCancellationRequested();
Diagnostic diagnostic;
if (TryRemoveCastExpression(model, cast, out diagnostic, cancellationToken))
{
result = result ?? new List<Diagnostic>();
result.Add(diagnostic);
}
}
return result;
}
private bool TryRemoveCastExpression(
SemanticModel model, CastExpressionSyntax node, out Diagnostic diagnostic, CancellationToken cancellationToken)
{
diagnostic = default(Diagnostic);
if (!node.IsUnnecessaryCast(model, cancellationToken))
{
return false;
}
var tree = model.SyntaxTree;
var span = TextSpan.FromBounds(node.OpenParenToken.SpanStart, node.CloseParenToken.Span.End);
if (tree.OverlapsHiddenPosition(span, cancellationToken))
{
return false;
}
diagnostic = Diagnostic.Create(DiagnosticMD, tree.GetLocation(span));
return true;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.SimplifyTypeNames
{
[ExportDiagnosticProvider(PredefinedDiagnosticProviderNames.SimplifyTypeNames, LanguageNames.CSharp)]
internal sealed class SimplifyTypeNamesDiagnosticProvider : ScopedDiagnosticProvider
{
internal const string DiagnosticId = "SimplifyTypeNames";
internal static readonly DiagnosticDescriptor DiagnosticMD = new DiagnosticDescriptor(DiagnosticId,
DiagnosticKind.Unnecessary,
CSharpFeaturesResources.SimplifyTypeName,
CSharpFeaturesResources.Name_can_be_simplified,
"Internal",
DiagnosticSeverity.None);
public override IEnumerable<DiagnosticDescriptor> GetSupportedDiagnostics()
{
return SpecializedCollections.SingletonEnumerable(DiagnosticMD);
}
protected override async Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(Document document, TextSpan span, CancellationToken cancellationToken)
{
if (!document.IsOpen())
{
return null;
}
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var node = root.FindNode(span);
List<Diagnostic> diagnostics = null;
diagnostics = ProcessNode(document, model, node, diagnostics, cancellationToken);
return diagnostics;
}
private List<Diagnostic> ProcessNode(Document document, SemanticModel model, SyntaxNode node, List<Diagnostic> result, CancellationToken cancellationToken)
{
Diagnostic diagnostic;
Func<SyntaxNode, bool> descendIntoChildren = n =>
{
if (!IsRegularCandidate(n) ||
!TrySimplifyTypeNameExpression(document, model, n, out diagnostic, cancellationToken))
{
return true;
}
result = result ?? new List<Diagnostic>();
result.Add(diagnostic);
return false;
};
// find regular node first - search from top to down. once found one, don't get into its children
foreach (var candidate in node.DescendantNodesAndSelf(descendIntoChildren))
{
cancellationToken.ThrowIfCancellationRequested();
}
// now search structure trivia
foreach (var candidate in node.DescendantNodesAndSelf(descendIntoChildren: n => !IsCrefCandidate(n), descendIntoTrivia: true))
{
cancellationToken.ThrowIfCancellationRequested();
if (IsCrefCandidate(candidate) &&
TrySimplifyTypeNameExpression(document, model, candidate, out diagnostic, cancellationToken))
{
result = result ?? new List<Diagnostic>();
result.Add(diagnostic);
}
}
return result;
}
private bool TrySimplifyTypeNameExpression(
Document document, SemanticModel model, SyntaxNode node, out Diagnostic diagnostic, CancellationToken cancellationToken)
{
diagnostic = default(Diagnostic);
var optionSet = document.Project.Solution.Workspace.GetOptions();
TextSpan issueSpan;
if (!CanSimplifyTypeNameExpression(model, node, optionSet, out issueSpan, cancellationToken))
{
return false;
}
if (model.SyntaxTree.OverlapsHiddenPosition(issueSpan, cancellationToken))
{
return false;
}
var tree = model.SyntaxTree;
diagnostic = Diagnostic.Create(DiagnosticMD, tree.GetLocation(issueSpan));
return true;
}
internal static bool IsCandidate(SyntaxNode node)
{
return IsRegularCandidate(node) || IsCrefCandidate(node);
}
private static bool IsRegularCandidate(SyntaxNode node)
{
return node is QualifiedNameSyntax ||
node is AliasQualifiedNameSyntax ||
node is MemberAccessExpressionSyntax ||
node is IdentifierNameSyntax ||
node is GenericNameSyntax ||
node is BinaryExpressionSyntax;
}
private static bool IsCrefCandidate(SyntaxNode node)
{
return node is QualifiedCrefSyntax;
}
internal static bool CanSimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, OptionSet optionSet, out TextSpan issueSpan, CancellationToken cancellationToken)
{
issueSpan = default(TextSpan);
// For Crefs, currently only Qualified Crefs needs to be handled separately
if (node.Kind() == SyntaxKind.QualifiedCref)
{
if (((QualifiedCrefSyntax)node).ContainsDiagnostics)
{
return false;
}
var crefSyntax = (CrefSyntax)node;
CrefSyntax replacementNode;
if (!crefSyntax.TryReduceOrSimplifyExplicitName(model, out replacementNode, out issueSpan, optionSet, cancellationToken))
{
return false;
}
}
else
{
var expression = (ExpressionSyntax)node;
if (expression.ContainsDiagnostics)
{
return false;
}
// in case of an As or Is expression we need to handle the binary expression, because it might be
// required to add parenthesis around the expression. Adding the parenthesis is done in the CSharpNameSimplifier.Rewriter
var expressionToCheck = expression.Kind() == SyntaxKind.AsExpression || expression.Kind() == SyntaxKind.IsExpression
? ((BinaryExpressionSyntax)expression).Right
: expression;
ExpressionSyntax replacementSyntax;
if (!expressionToCheck.TryReduceOrSimplifyExplicitName(model, out replacementSyntax, out issueSpan, optionSet, cancellationToken))
{
return false;
}
}
return true;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings
{
[ExportLanguageService(typeof(ICodeRefactoringService), LanguageNames.CSharp)]
internal class CSharpCodeRefactoringService : AbstractCodeRefactoringService
{
private readonly IEnumerable<Lazy<CodeRefactoringProvider, OrderableLanguageMetadata>> lazyCodeRefactoringProviders;
private IEnumerable<CodeRefactoringProvider> defaultCodeRefactoringProviders;
[ImportingConstructor]
public CSharpCodeRefactoringService(
[ImportMany] IEnumerable<Lazy<CodeRefactoringProvider, OrderableLanguageMetadata>> codeRefactoringProviders)
{
this.lazyCodeRefactoringProviders = ExtensionOrderer.Order(codeRefactoringProviders.Where(p => p.Metadata.Language == LanguageNames.CSharp)).ToImmutableList();
}
public override IEnumerable<CodeRefactoringProvider> GetDefaultCodeRefactoringProviders()
{
if (this.defaultCodeRefactoringProviders == null)
{
System.Threading.Interlocked.CompareExchange(ref this.defaultCodeRefactoringProviders, this.lazyCodeRefactoringProviders.Select(lz => lz.Value).ToImmutableList(), null);
}
return defaultCodeRefactoringProviders;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CSharpWorkspaces")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CSharpWorkspaces")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("097ac50a-cde0-461f-b95a-f7e237ccfb73")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Extensions;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CodeRefactorings
{
internal abstract partial class AbstractCodeRefactoringService : ICodeRefactoringService
{
private static readonly Func<CodeRefactoringProvider, TextSpan, string> codeRefactoringDescription =
(p, s) => string.Format("{0} ({1})", p.ToString(), s);
public abstract IEnumerable<CodeRefactoringProvider> GetDefaultCodeRefactoringProviders();
public async Task<IEnumerable<CodeRefactoring>> GetRefactoringsAsync(
Document document,
TextSpan textSpan,
IEnumerable<CodeRefactoringProvider> providers,
CancellationToken cancellationToken)
{
providers = providers ?? this.GetDefaultCodeRefactoringProviders();
var result = new List<CodeRefactoring>();
var extensionManager = document.GetExtensionManager();
var context = new CodeRefactoringContext(document, textSpan, cancellationToken);
foreach (var provider in providers)
{
await AddRefactoringAsync(provider, result, extensionManager, context).ConfigureAwait(false);
}
return result;
}
private async Task AddRefactoringAsync(
CodeRefactoringProvider provider,
List<CodeRefactoring> allRefactorings,
IExtensionManager extensionManager,
CodeRefactoringContext context)
{
try
{
if (!extensionManager.IsDisabled(provider))
{
using (Logger.LogBlock(FeatureId.CodeActions, FunctionId.CodeAction_AddRefactoring, codeRefactoringDescription, provider, context.Span, context.CancellationToken))
{
var actions = await provider.GetRefactoringsAsync(context).ConfigureAwait(false);
if (actions != null && actions.Count() > 0)
{
allRefactorings.Add(new CodeRefactoring(provider, actions));
}
}
}
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception e)
{
extensionManager.HandleException(provider, e);
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Snippets;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Completion
{
internal abstract partial class AbstractCompletionService : ICompletionService
{
private static readonly Func<string, List<CompletionItem>> s_createList = _ => new List<CompletionItem>();
private const int MruSize = 10;
private readonly List<string> _committedItems = new List<string>(MruSize);
private readonly object _mruGate = new object();
internal void CompletionItemCommitted(CompletionItem item)
{
lock (_mruGate)
{
// We need to remove the item if it's already in the list.
// If we're at capacity, we need to remove the LRU item.
var removed = _committedItems.Remove(item.DisplayText);
if (!removed && _committedItems.Count == MruSize)
{
_committedItems.RemoveAt(0);
}
_committedItems.Add(item.DisplayText);
}
}
internal int GetMRUIndex(CompletionItem item)
{
lock (_mruGate)
{
// A lower value indicates more recently used. Since items are added
// to the end of the list, our result just maps to the negation of the
// index.
// -1 => 1 == Not Found
// 0 => 0 == least recently used
// 9 => -9 == most recently used
var index = _committedItems.IndexOf(item.DisplayText);
return -index;
}
}
public void ClearMRUCache()
{
lock (_mruGate)
{
_committedItems.Clear();
}
}
/// <summary>
/// Apply any culture-specific quirks to the given text for the purposes of pattern matching.
/// For example, in the Turkish locale, capital 'i's should be treated specially in Visual Basic.
/// </summary>
public virtual string GetCultureSpecificQuirks(string candidate)
{
return candidate;
}
public abstract IEnumerable<CompletionListProvider> GetDefaultCompletionProviders();
protected abstract string GetLanguageName();
private class ProviderList
{
public CompletionListProvider Provider;
public CompletionList List;
}
public async Task<CompletionList> GetCompletionListAsync(
Document document,
int position,
CompletionTriggerInfo triggerInfo,
OptionSet options,
IEnumerable<CompletionListProvider> providers,
CancellationToken cancellationToken)
{
options = options ?? document.Project.Solution.Workspace.Options;
providers = providers ?? GetDefaultCompletionProviders();
var completionProviderToIndex = GetCompletionProviderToIndex(providers);
var completionRules = GetCompletionRules();
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
IEnumerable<CompletionListProvider> triggeredProviders;
switch (triggerInfo.TriggerReason)
{
case CompletionTriggerReason.TypeCharCommand:
triggeredProviders = providers.Where(p => p.IsTriggerCharacter(text, position - 1, options)).ToList();
break;
case CompletionTriggerReason.BackspaceOrDeleteCommand:
triggeredProviders = this.TriggerOnBackspace(text, position, triggerInfo, options)
? providers
: SpecializedCollections.EmptyEnumerable<CompletionListProvider>();
break;
default:
triggeredProviders = providers;
break;
}
// Now, ask all the triggered providers if they can provide a group.
var providersAndLists = new List<ProviderList>();
foreach (var provider in triggeredProviders)
{
var completionList = await GetCompletionListAsync(provider, document, position, triggerInfo, options, cancellationToken).ConfigureAwait(false);
if (completionList != null)
{
providersAndLists.Add(new ProviderList { Provider = provider, List = completionList });
}
}
// See if there was a group provided that was exclusive and had items in it. If so, then
// that's all we'll return.
var firstExclusiveList = providersAndLists.FirstOrDefault(
t => t.List.IsExclusive && t.List.Items.Any());
if (firstExclusiveList != null)
{
return MergeAndPruneCompletionLists(SpecializedCollections.SingletonEnumerable(firstExclusiveList.List), completionRules);
}
// If no exclusive providers provided anything, then go through the remaining
// triggered list and see if any provide items.
var nonExclusiveLists = providersAndLists.Where(t => !t.List.IsExclusive).ToList();
// If we still don't have any items, then we're definitely done.
if (!nonExclusiveLists.Any(g => g.List.Items.Any()))
{
return null;
}
// If we do have items, then ask all the other (non exclusive providers) if they
// want to augment the items.
var usedProviders = nonExclusiveLists.Select(g => g.Provider);
var nonUsedProviders = providers.Except(usedProviders);
var nonUsedNonExclusiveProviders = new List<ProviderList>();
foreach (var provider in nonUsedProviders)
{
var completionList = await GetCompletionListAsync(provider, document, position, triggerInfo, options, cancellationToken).ConfigureAwait(false);
if (completionList != null && !completionList.IsExclusive)
{
nonUsedNonExclusiveProviders.Add(new ProviderList { Provider = provider, List = completionList });
}
}
var allProvidersAndLists = nonExclusiveLists.Concat(nonUsedNonExclusiveProviders).ToList();
if (allProvidersAndLists.Count == 0)
{
return null;
}
// Providers are ordered, but we processed them in our own order. Ensure that the
// groups are properly ordered based on the original providers.
allProvidersAndLists.Sort((p1, p2) => completionProviderToIndex[p1.Provider] - completionProviderToIndex[p2.Provider]);
return MergeAndPruneCompletionLists(allProvidersAndLists.Select(g => g.List), completionRules);
}
private static CompletionList MergeAndPruneCompletionLists(IEnumerable<CompletionList> completionLists, CompletionRules completionRules)
{
var displayNameToItemsMap = new Dictionary<string, List<CompletionItem>>();
CompletionItem builder = null;
foreach (var completionList in completionLists)
{
Contract.Assert(completionList != null);
foreach (var item in completionList.Items)
{
Contract.Assert(item != null);
// New items that match an existing item will replace it.
ReplaceExistingItem(item, displayNameToItemsMap, completionRules);
}
builder = builder ?? completionList.Builder;
}
if (displayNameToItemsMap.Count == 0)
{
return null;
}
// TODO(DustinCa): Revisit performance of this.
var totalItems = displayNameToItemsMap.Values.Flatten().ToList();
totalItems.Sort();
// TODO(DustinCa): This is lossy -- we lose the IsExclusive field. Fix that.
return new CompletionList(totalItems.ToImmutableArray(), builder);
}
private static void ReplaceExistingItem(
CompletionItem item,
Dictionary<string, List<CompletionItem>> displayNameToItemsMap,
CompletionRules completionRules)
{
// See if we have an item with
var sameNamedItems = displayNameToItemsMap.GetOrAdd(item.DisplayText, s_createList);
for (int i = 0; i < sameNamedItems.Count; i++)
{
var existingItem = sameNamedItems[i];
Contract.Assert(item.DisplayText == existingItem.DisplayText);
if (completionRules.ItemsMatch(item, existingItem))
{
sameNamedItems[i] = Disambiguate(item, existingItem);
return;
}
}
sameNamedItems.Add(item);
}
private static CompletionItem Disambiguate(CompletionItem item, CompletionItem existingItem)
{
// We've constructed the export order of completion providers so
// that snippets are exported after everything else. That way,
// when we choose a single item per display text, snippet
// glyphs appear by snippets. This breaks preselection of items
// whose display text is also a snippet (workitem 852578),
// the snippet item doesn't have its preselect bit set.
// We'll special case this by not preferring later items
// if they are snippets and the other candidate is preselected.
if (existingItem.MatchPriority != MatchPriority.Default && item.CompletionProvider is ISnippetCompletionProvider)
{
return existingItem;
}
// If one is a keyword, and the other is some other item that inserts the same text as the keyword,
// keep the keyword
var keywordItem = existingItem as KeywordCompletionItem ?? item as KeywordCompletionItem;
if (keywordItem != null)
{
return keywordItem;
}
return item;
}
private Dictionary<CompletionListProvider, int> GetCompletionProviderToIndex(IEnumerable<CompletionListProvider> completionProviders)
{
var result = new Dictionary<CompletionListProvider, int>();
int i = 0;
foreach (var completionProvider in completionProviders)
{
result[completionProvider] = i;
i++;
}
return result;
}
private static async Task<CompletionList> GetCompletionListAsync(
CompletionListProvider provider,
Document document,
int position,
CompletionTriggerInfo triggerInfo,
OptionSet options,
CancellationToken cancellationToken)
{
var context = new CompletionListContext(document, position, triggerInfo, options, cancellationToken);
if (document.SupportsSyntaxTree)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
if (!root.FullSpan.IntersectsWith(position))
{
try
{
// Trying to track down source of https://github.com/dotnet/roslyn/issues/9325
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
ReportException(position, root, sourceText);
}
catch (Exception e) when (FatalError.ReportWithoutCrash(e))
{
}
}
else
{
await provider.ProduceCompletionListAsync(context).ConfigureAwait(false);
}
}
else
{
await provider.ProduceCompletionListAsync(context).ConfigureAwait(false);
}
return new CompletionList(context.GetItems(), context.Builder, context.IsExclusive);
}
private static void ReportException(int position, SyntaxNode root, SourceText sourceText)
{
throw new InvalidOperationException(
$"Position '{position}' is not contained in SyntaxTree Span '{root.FullSpan}' source text length '{sourceText.Length}'");
}
public bool IsTriggerCharacter(SourceText text, int characterPosition, IEnumerable<CompletionListProvider> completionProviders, OptionSet options)
{
if (!options.GetOption(CompletionOptions.TriggerOnTyping, GetLanguageName()))
{
return false;
}
completionProviders = completionProviders ?? GetDefaultCompletionProviders();
return completionProviders.Any(p => p.IsTriggerCharacter(text, characterPosition, options));
}
protected abstract bool TriggerOnBackspace(SourceText text, int position, CompletionTriggerInfo triggerInfo, OptionSet options);
public abstract Task<TextSpan> GetDefaultTrackingSpanAsync(Document document, int position, CancellationToken cancellationToken);
public virtual CompletionRules GetCompletionRules()
{
return new CompletionRules(this);
}
public virtual bool DismissIfEmpty
{
get { return false; }
}
public Task<string> GetSnippetExpansionNoteForCompletionItemAsync(CompletionItem completionItem, Workspace workspace)
{
var insertionText = GetCompletionRules().GetTextChange(completionItem, '\t').NewText;
var snippetInfoService = workspace.Services.GetLanguageServices(GetLanguageName()).GetService<ISnippetInfoService>();
if (snippetInfoService != null && snippetInfoService.SnippetShortcutExists_NonBlocking(insertionText))
{
return Task.FromResult(string.Format(FeaturesResources.Note_colon_Tab_twice_to_insert_the_0_snippet, insertionText));
}
return SpecializedTasks.Default<string>();
}
public virtual bool SupportSnippetCompletionListOnTab
{
get { return false; }
}
public virtual bool DismissIfLastFilterCharacterDeleted
{
get { return false; }
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Completion
{
internal interface ICompletionService : ILanguageService
{
/// <summary>
/// Returns the default set of completion providers for this completion service.
/// </summary>
IEnumerable<CompletionListProvider> GetDefaultCompletionProviders();
/// <summary>
/// Returns the set of completion rules for this completion service.
/// </summary>
CompletionRules GetCompletionRules();
/// <summary>
/// Clears the most-recently-used cache used by completion.
/// </summary>
void ClearMRUCache();
/// <summary>
/// Returns the <see cref="CompletionList"/> for the specified position in the document.
/// </summary>
Task<CompletionList> GetCompletionListAsync(
Document document,
int position,
CompletionTriggerInfo triggerInfo,
OptionSet options,
IEnumerable<CompletionListProvider> providers,
CancellationToken cancellationToken);
/// <summary>
/// Returns true if the character at the specific position in the document should trigger
/// completion.
/// </summary>
bool IsTriggerCharacter(SourceText text, int characterPosition, IEnumerable<CompletionListProvider> completionProviders, OptionSet optionSet);
/// <summary>
/// Get the default tracking span, based on the language, that providers are likely to use.
/// </summary>
Task<TextSpan> GetDefaultTrackingSpanAsync(Document document, int position, CancellationToken cancellationToken);
/// <summary>
/// Returns a string that should be added to the description of the given completion item
/// if a snippet exists with a shortcut that matches the completion item's insertion text.
/// </summary>
Task<string> GetSnippetExpansionNoteForCompletionItemAsync(CompletionItem completionItem, Workspace workspace);
/// <summary>
/// True if the completion list should be dismissed if the user's typing causes it to filter
/// and display no items.
/// </summary>
bool DismissIfEmpty { get; }
/// <summary>
/// True if typing ?[tab] should try to show the list of available snippets.
/// </summary>
bool SupportSnippetCompletionListOnTab { get; }
/// <summary>
/// True if the list should be dismissed when the user deletes the last character in the filter span.
/// </summary>
bool DismissIfLastFilterCharacterDeleted { get; }
}
}
......@@ -117,12 +117,6 @@
<ItemGroup>
<PackageReference Include="System.Reflection" Version="$(SystemReflectionVersion)" />
</ItemGroup>
<ItemGroup>
<Compile Remove="CodeRefactorings\AbstractCodeRefactoringService.cs" />
<Compile Remove="Completion\AbstractCompletionService.cs" />
<Compile Remove="Completion\ICompletionService.cs" />
<Compile Remove="Shared\Extensions\ILanguageMetadataExtensions.cs" />
</ItemGroup>
<Import Project="..\..\..\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.LanguageServices;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Shared.Extensions
{
internal static class ILanguageMetadataExtensions
{
public static TInterface ToSpecificLanguage<TInterface, TMetadata>(this IEnumerable<Lazy<TInterface, TMetadata>> services, string languageName)
where TMetadata : ILanguageMetadata
{
return services.Where(s => s.Metadata.Language == languageName).Select(s => s.Value).FirstOrDefault();
}
public static IEnumerable<TInterface> FilterToSpecificLanguage<TInterface, TMetadata>(this IEnumerable<Lazy<TInterface, TMetadata>> services, string languageName)
where TMetadata : ILanguageMetadata
{
return services.Where(s => s.Metadata.Language == languageName).Select(s => s.Value);
}
public static Dictionary<string, List<Lazy<TInterface, TMetadata>>> ToPerLanguageMap<TInterface, TMetadata>(this IEnumerable<Lazy<TInterface, TMetadata>> services)
where TMetadata : ILanguageMetadata
{
var map = new Dictionary<string, List<Lazy<TInterface, TMetadata>>>();
foreach (var service in services)
{
var list = map.GetOrAdd(service.Metadata.Language, _ => new List<Lazy<TInterface, TMetadata>>());
list.Add(service);
}
return map;
}
}
}
......@@ -83,9 +83,6 @@
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
<ItemGroup>
<Compile Remove="CodeRefactorings\VisualBasicCodeRefactoringService.vb" />
</ItemGroup>
<Import Project="..\..\..\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.ComponentModel.Composition
Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.LanguageServices
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings
<ExportLanguageService(GetType(ICodeRefactoringService), LanguageNames.VisualBasic)>
Friend Class VisualBasicCodeRefactoringService
Inherits AbstractCodeRefactoringService
Private ReadOnly lazyCodeRefactoringProviders As IEnumerable(Of Lazy(Of CodeRefactoringProvider, OrderableLanguageMetadata))
Private defaultCodeRefactoringProviders As IEnumerable(Of CodeRefactoringProvider)
<ImportingConstructor>
Public Sub New(<ImportMany> codeRefactoringProviders As IEnumerable(Of Lazy(Of CodeRefactoringProvider, OrderableLanguageMetadata)))
Me.lazyCodeRefactoringProviders = ExtensionOrderer.Order(codeRefactoringProviders.Where(Function(p) p.Metadata.Language = LanguageNames.VisualBasic)).ToImmutableList()
End Sub
Public Overrides Function GetDefaultCodeRefactoringProviders() As IEnumerable(Of CodeRefactoringProvider)
If (Me.defaultCodeRefactoringProviders Is Nothing) Then
Threading.Interlocked.CompareExchange(Of IEnumerable(Of CodeRefactoringProvider))(Me.defaultCodeRefactoringProviders, Me.lazyCodeRefactoringProviders.Select(Function(lz) lz.Value).ToImmutableList(), Nothing)
End If
Return defaultCodeRefactoringProviders
End Function
End Class
End Namespace
......@@ -149,8 +149,5 @@
<ItemGroup>
<Content Include="CSharpPackageRegistration.pkgdef" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Options\CSharpSettingsSerializer.cs" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Compilers;
using Microsoft.CodeAnalysis.Services.CSharp.Formatting;
using Microsoft.CodeAnalysis.Services.Formatting;
using Microsoft.CodeAnalysis.Services.OptionService;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualStudio.Services;
using Microsoft.CodeAnalysis.VisualStudio.Services.Implementation.Options;
using Microsoft.VisualStudio.Shell;
namespace Microsoft.CodeAnalysis.VisualStudio.CSharp.Options
{
[ExportOptionSerializer(AllLanguageOptionReferences.TabFeatureName)]
internal sealed class CSharpSettingsSerializer : AbstractLanguageSettingsSerializer
{
[ImportingConstructor]
public CSharpSettingsSerializer(SVsServiceProvider serviceProvider)
: base(Guids.CSharpLanguageServiceId, serviceProvider)
{
}
public override bool TryFetch(OptionInfo option, string language, out object value)
{
if (language != LanguageNames.CSharp)
{
value = null;
return false;
}
if (option.Key.Equals(AllLanguageOptionReferences.UseTab))
{
value = languageSetting.fInsertTabs != 0;
return true;
}
if (option.Key == AllLanguageOptionReferences.TabSize)
{
value = (int)languageSetting.uTabSize;
return true;
}
if (option.Key == AllLanguageOptionReferences.IndentationSize)
{
value = (int)languageSetting.uIndentSize;
return true;
}
if (option.Key == AllLanguageOptionReferences.DebugMode)
{
value = option.DefaultValue;
return true;
}
value = null;
return false;
}
public override bool TryPersist(OptionInfo option, string language, object value)
{
if (language != LanguageNames.CSharp)
{
value = null;
return false;
}
if (option.Key == AllLanguageOptionReferences.UseTab)
{
languageSetting.fInsertTabs = (uint)((bool)value ? 1 : 0);
SetUserPreferences();
return true;
}
if (option.Key == AllLanguageOptionReferences.TabSize)
{
languageSetting.uTabSize = (uint)value;
SetUserPreferences();
return true;
}
if (option.Key == AllLanguageOptionReferences.IndentationSize)
{
languageSetting.uIndentSize = (uint)value;
SetUserPreferences();
return true;
}
if (option.Key == AllLanguageOptionReferences.DebugMode)
{
// Currently we don't store it.
return true;
}
return false;
}
}
}
......@@ -198,6 +198,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Debugging\ProximityExpressionsGetterTestFile.cs" />
<Compile Remove="Debugging\ProximityExpressionsGetterTestFile.cs" />
<Compile Update="Debugging\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
......@@ -214,9 +215,5 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Compile Remove="CompilationErrorTelemetry\CompilationErrorTelemetryTests.cs" />
<Compile Remove="Debugging\ProximityExpressionsGetterTestFile.cs" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.VisualStudio.LanguageServices.CSharp.CompilationErrorTelemetry;
using Xunit;
namespace Microsoft.VisualStudio.LanguageServices.CSharp.UnitTests.CompilationErrorTelemetry
{
public class CompilationErrorTelemetryTests
{
public TestWorkspace CreateCSharpWorkspaceWithLineOfCode(string lineOfCode, string otherContent, string usings)
{
string code = usings +
Environment.NewLine +
Environment.NewLine + @"
namespace CompilationErrorTest
{
" +
@" class Program
{"
+ otherContent +
Environment.NewLine
+ Environment.NewLine + @"
static void Main(string[] args)
{" + Environment.NewLine +
lineOfCode +
Environment.NewLine + @"
}
}
}
";
return CSharpWorkspaceFactory.CreateWorkspaceFromFile(code, exportProvider: null);
}
private async Task<List<CompilationErrorDetails>> GetErrorDetailsFromLineOfCodeAsync(string lineOfCode)
{
return await GetErrorDetailsFromLineOfCodeAsync(lineOfCode, "").ConfigureAwait(false);
}
private async Task<List<CompilationErrorDetails>> GetErrorDetailsFromLineOfCodeAsync(string lineOfCode, string otherContent)
{
string defaultUsings = "using System.Collections.Generic; using System.IO";
return await GetErrorDetailsFromLineOfCodeAsync(lineOfCode, otherContent, defaultUsings).ConfigureAwait(false);
}
private async Task<List<CompilationErrorDetails>> GetErrorDetailsFromLineOfCodeAsync(string lineOfCode, string otherContent, string usings)
{
using (var workspace = CreateCSharpWorkspaceWithLineOfCode(lineOfCode, otherContent, usings))
{
var errorDetailDiscoverer = new CompilationErrorDetailDiscoverer();
var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id);
var errorDetails = await errorDetailDiscoverer.GetCompilationErrorDetails(document, null, CancellationToken.None).ConfigureAwait(false);
return errorDetails;
}
}
[Fact]
public async Task TestErrorCS0103()
{
string lineOfCode = "if (notdeclared != null) { }";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var errorDetail = errorDetails[0];
Assert.Equal("CS0103", errorDetail.ErrorId);
Assert.Equal("notdeclared", errorDetail.UnresolvedMemberName);
Assert.Equal(null, errorDetail.LeftExpressionDocId);
Assert.Equal(null, errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(null, errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS1061()
{
string lineOfCode = "new FileStream(\"test.txt\", FileMode.Truncate).MissingMethod();";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var errorDetail = errorDetails[0];
Assert.Equal("CS1061", errorDetail.ErrorId);
Assert.Equal("MissingMethod", errorDetail.UnresolvedMemberName);
Assert.Equal("T:System.IO.FileStream", errorDetail.LeftExpressionDocId);
Assert.Equal(new string[] { "T:System.IO.Stream", "T:System.MarshalByRefObject", "T:System.Object" }, errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(null, errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS1061Generic()
{
string lineOfCode = "new List<string>().Length;";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var errorDetail = errorDetails[0];
Assert.Equal("CS1061", errorDetail.ErrorId);
Assert.Equal("Length", errorDetail.UnresolvedMemberName);
Assert.Equal("T:System.Collections.Generic.List`1", errorDetail.LeftExpressionDocId);
Assert.Equal(new string[] { "T:System.Object" }, errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(null, errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS0246()
{
string lineOfCode = "NotAType x;";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var errorDetail = errorDetails[0];
Assert.Equal("CS0246", errorDetail.ErrorId);
Assert.Equal("NotAType", errorDetail.UnresolvedMemberName);
Assert.Equal(null, errorDetail.LeftExpressionDocId);
Assert.Equal(null, errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(null, errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS0305()
{
string lineOfCode = "IEnumerable<string, string> wrongTypeArgCount;";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var errorDetail = errorDetails[0];
Assert.Equal("CS0305", errorDetail.ErrorId);
Assert.Equal("IEnumerable", errorDetail.UnresolvedMemberName);
Assert.Equal(null, errorDetail.LeftExpressionDocId);
Assert.Equal(null, errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(new string[] { "T:System.String", "T:System.String" }, errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS0305WithUnresolvedTypeArgument()
{
string lineOfCode = "IEnumerable<string, NotAType> wrongTypeArgCount;";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(2, errorDetails.Count);
var cs0305errorDetail = errorDetails[0];
Assert.Equal("CS0305", cs0305errorDetail.ErrorId);
Assert.Equal("IEnumerable", cs0305errorDetail.UnresolvedMemberName);
Assert.Equal(null, cs0305errorDetail.LeftExpressionDocId);
Assert.Equal(null, cs0305errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(new string[] { "T:System.String", "!:NotAType" }, cs0305errorDetail.GenericArguments);
var cs0246errorDetail = errorDetails[1];
Assert.Equal("CS0246", cs0246errorDetail.ErrorId);
Assert.Equal("NotAType", cs0246errorDetail.UnresolvedMemberName);
Assert.Equal(null, cs0246errorDetail.LeftExpressionDocId);
Assert.Equal(null, cs0246errorDetail.LeftExpressionBaseTypeDocIds);
}
[Fact]
public async Task TestErrorCS0308()
{
string lineOfCode = " F<int>(); ";
string nonGenericFunction = @"public void F() {}";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode, nonGenericFunction).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var cs0308errorDetail = errorDetails[0];
Assert.Equal("CS0308", cs0308errorDetail.ErrorId);
Assert.Equal("F", cs0308errorDetail.UnresolvedMemberName);
Assert.Equal(null, cs0308errorDetail.LeftExpressionDocId);
Assert.Equal(null, cs0308errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(new string[] { "T:System.Int32" }, cs0308errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS0308WithGenericReturnType()
{
string lineOfCode = "";
string usings = "using System.Collections;";
string genericTypeWithGenericReturnValue = @"public class MyGenericType<T>
{
private T[] items = new T[100];
public IEnumerator<T> GetEnumerator() // CS0308
{
for (int i = 0; i < items.Length; i++)
yield return items[i];
}
}";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode, genericTypeWithGenericReturnValue, usings).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var cs0308errorDetail = errorDetails[0];
Assert.Equal("CS0308", cs0308errorDetail.ErrorId);
Assert.Equal("IEnumerator", cs0308errorDetail.UnresolvedMemberName);
Assert.Equal(null, cs0308errorDetail.LeftExpressionDocId);
Assert.Equal(null, cs0308errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(new string[] { "!:T" }, cs0308errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS0616()
{
string lineOfCode = "[Program]\n public void SomeMethod() { }";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var cs0616errorDetail = errorDetails[0];
Assert.Equal("CS0616", cs0616errorDetail.ErrorId);
Assert.Equal("T:CompilationErrorTest.Program", cs0616errorDetail.UnresolvedMemberName);
Assert.Equal(null, cs0616errorDetail.LeftExpressionDocId);
Assert.Equal(null, cs0616errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(null, cs0616errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS1503()
{
string lineOfCode = "System.IO.FileStream CS1503 = System.IO.File.Open(123.4f, System.IO.FileMode.Open);";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var cs1503errorDetail = errorDetails[0];
Assert.Equal("CS1503", cs1503errorDetail.ErrorId);
Assert.Equal("Open", cs1503errorDetail.MethodName);
Assert.Equal(new string[] { "T:System.Single", "T:System.IO.FileMode" }, cs1503errorDetail.ArgumentTypes);
Assert.Equal(null, cs1503errorDetail.UnresolvedMemberName);
Assert.Equal("T:System.IO.File", cs1503errorDetail.LeftExpressionDocId);
Assert.Equal(null, cs1503errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(null, cs1503errorDetail.GenericArguments);
}
[Fact]
public async Task TestErrorCS1935()
{
string lineOfCode = "IEnumerable<int> e = from n in new int[] { 0, 1, 2, 3, 4, 5 } where n > 3 select n;";
var errorDetails = await GetErrorDetailsFromLineOfCodeAsync(lineOfCode).ConfigureAwait(false);
Assert.Equal(1, errorDetails.Count);
var errorDetail = errorDetails[0];
Assert.Equal("CS1935", errorDetail.ErrorId);
Assert.Equal(null, errorDetail.UnresolvedMemberName);
Assert.Equal(null, errorDetail.LeftExpressionDocId);
Assert.Equal(null, errorDetail.LeftExpressionBaseTypeDocIds);
Assert.Equal(null, errorDetail.GenericArguments);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Composition;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.ErrorLogger;
using Microsoft.CodeAnalysis.Host;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Log
{
[ExportWorkspaceServiceFactory(typeof(IErrorLogger), ServiceLayer.Host), Shared]
internal sealed class VisualStudioErrorLoggerFactory : IWorkspaceServiceFactory
{
private IErrorLogger _singleton;
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
return _singleton ?? (_singleton = new VisualStudioErrorLogger());
}
}
}
......@@ -272,9 +272,6 @@
<SubType>Designer</SubType>
</VSCTCompile>
</ItemGroup>
<ItemGroup>
<Compile Remove="Implementation\Log\VisualStudioErrorLoggerFactory.cs" />
</ItemGroup>
<Import Project="..\..\..\Dependencies\CodeAnalysis.Debugging\Microsoft.CodeAnalysis.Debugging.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Serialization;
using Xunit;
namespace Roslyn.VisualStudio.Next.UnitTests.Remote
{
internal static class TestUtils
{
public static Dictionary<Checksum, object> GetAssetMap(this Solution solution)
{
var map = new Dictionary<Checksum, object>();
AppendAssetMap(solution, map);
return map;
}
public static Dictionary<Checksum, object> GetAssetMap(this Project project)
{
var map = new Dictionary<Checksum, object>();
AppendAssetMap(project, map);
return map;
}
public static void AppendAssetMap(this Solution solution, Dictionary<Checksum, object> map)
{
SolutionStateChecksums solutionChecksums;
Assert.True(solution.State.TryGetStateChecksums(out solutionChecksums));
solutionChecksums.Find(solution.State, Flatten(solutionChecksums), map, CancellationToken.None);
foreach (var project in solution.Projects)
{
AppendAssetMap(project, map);
}
}
private static void AppendAssetMap(Project project, Dictionary<Checksum, object> map)
{
ProjectStateChecksums projectChecksums;
if (!project.State.TryGetStateChecksums(out projectChecksums))
{
Assert.False(RemoteSupportedLanguages.IsSupported(project.Language));
return;
}
projectChecksums.Find(project.State, Flatten(projectChecksums), map, CancellationToken.None);
foreach (var document in project.Documents)
{
AppendAssetMap(document, map);
}
foreach (var document in project.AdditionalDocuments)
{
AppendAssetMap(document, map);
}
}
private static void AppendAssetMap(TextDocument document, Dictionary<Checksum, object> map)
{
DocumentStateChecksums documentChecksums;
Assert.True(document.State.TryGetStateChecksums(out documentChecksums));
documentChecksums.Find(document.State, Flatten(documentChecksums), map, CancellationToken.None);
// fix up due to source text can't be obtained synchronously in product code
map[documentChecksums.Text] = document.State.GetTextSynchronously(CancellationToken.None);
}
private static HashSet<Checksum> Flatten(ChecksumWithChildren checksums)
{
var set = new HashSet<Checksum>();
set.Add(checksums.Checksum);
foreach (var child in checksums.Children)
{
var checksum = child as Checksum;
if (checksum != null)
{
set.Add(checksum);
}
var collection = child as ChecksumCollection;
if (collection != null)
{
foreach (var item in collection)
{
set.Add(item);
}
}
}
return set;
}
}
}
......@@ -196,8 +196,5 @@
<ItemGroup>
<InternalsVisibleToMoq Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<Compile Remove="TestUtils.cs" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
......@@ -210,8 +210,8 @@
<Folder Include="My Project\" />
</ItemGroup>
<ItemGroup>
<!--<Compile Include="ExtractInterface\ExtractInterfaceViewModelTests.vb" />-->
<Content Include="Debugging\ProximityExpressionsGetterTestFile.vb" />
<Compile Remove="Debugging\ProximityExpressionsGetterTestFile.vb" />
<Compile Update="Debugging\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
......@@ -228,8 +228,5 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Debugging\ProximityExpressionsGetterTestFile.vb" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.VisualStudio.IntegrationTest.Utilities;
using Xunit;
namespace Roslyn.VisualStudio.IntegrationTests.CSharp
{
[Collection(nameof(SharedIntegrationHostFixture))]
public class CSharpAsyncOutput : AbstractInteractiveWindowTest
{
public CSharpAsyncOutput(VisualStudioInstanceFactory instanceFactory)
: base(instanceFactory)
{
}
[Fact]
public void VerifyPreviousAndNextHistory()
{
SubmitText(@"#prompt inline ""@@@"" "" """, waitForPrompt: false);
SubmitText(@"#cls", waitForPrompt: false);
SubmitText(@"using System.Threading;
var t1 = new Thread(() => { for (int i = 0; ; i++) { Console.WriteLine('$'); Thread.Sleep(500); } });
var t2 = new Thread(() => { for (int i = 0; ; i++) { Console.Write('$'); Thread.Sleep(101); } });
var t3 = new Thread(() => { while (true) { Console.Write('\r'); Thread.Sleep(1200); } });
t1.Start();
t2.Start();
t3.Start();", waitForPrompt: false);
SubmitText(@"#help", waitForPrompt: false);
Wait(seconds: 1);
SubmitText(@"1+1", waitForPrompt: false);
Wait(seconds: 1);
SubmitText(@"1+2", waitForPrompt: false);
Wait(seconds: 1);
VerifyReplPromptConsistency(prompt: "@@@", output: "$");
SubmitText(@"#prompt margin", waitForPrompt: false);
Wait(seconds: 1);
SubmitText(@"1+4", waitForPrompt: false);
SubmitText(@"#prompt inline", waitForPrompt: false);
Wait(seconds: 1);
SubmitText(@"1+5");
Wait(seconds: 1);
VerifyReplPromptConsistency(prompt: "@@@", output: "$");
SubmitText(@"#cls", waitForPrompt: false);
SubmitText(@"1+5", waitForPrompt: false);
Wait(seconds: 1);
VerifyReplPromptConsistency(prompt: "@@@", output: "$");
SubmitText(@"#prompt inline "" > "" "". """, waitForPrompt: false);
SubmitText(@"t1.Abort();
t1.Join();
t2.Abort();
t2.Join();
t3.Abort();
t3.Join();");
ClearReplText();
SubmitText(@"#prompt inline "" > "" "". """);
Reset(waitForPrompt: true);
}
}
}
......@@ -173,8 +173,5 @@
<PackageReference Include="xunit" Version="$(xunitVersion)" />
<PackageReference Include="xunit.runner.console" Version="$(xunitrunnerconsoleVersion)" />
</ItemGroup>
<ItemGroup>
<Compile Remove="CSharp\CSharpAsyncOutput.cs" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using Microsoft.VisualStudio.Shell;
namespace Roslyn.VisualStudio.Setup
{
/// <summary>
/// A <see cref="RegistrationAttribute"/> that provides binding redirects with all of the Roslyn settings we need.
/// It's just a wrapper for <see cref="ProvideBindingRedirectionAttribute"/> that sets all the defaults rather than duplicating them.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class ProvideRoslynBindingRedirectionAttribute : RegistrationAttribute
{
private readonly ProvideBindingRedirectionAttribute _redirectionAttribute;
public ProvideRoslynBindingRedirectionAttribute(string fileName)
{
// ProvideBindingRedirectionAttribute is sealed, so we can't inherit from it to provide defaults.
// Instead, we'll do more of an aggregation pattern here.
// Note that PublicKeyToken, NewVersion and OldVersionUpperBound are read from the actual assembly version of the dll.
_redirectionAttribute = new ProvideBindingRedirectionAttribute {
AssemblyName = Path.GetFileNameWithoutExtension(fileName),
OldVersionLowerBound = "0.0.0.0",
CodeBase = fileName,
};
}
public override void Register(RegistrationContext context)
{
_redirectionAttribute.Register(context);
// Opt into overriding the devenv.exe.config binding redirect
using (var key = context.CreateKey($@"RuntimeConfiguration\dependentAssembly\bindingRedirection\{_redirectionAttribute.Guid.ToString("B").ToUpperInvariant()}"))
{
key.SetValue("isPkgDefOverrideEnabled", true);
}
}
public override void Unregister(RegistrationContext context)
=> _redirectionAttribute.Unregister(context);
}
}
......@@ -106,8 +106,5 @@
<PackageReference Include="System.Xml.XmlDocument" Version="$(SystemXmlXmlDocumentVersion)" />
<PackageReference Include="System.Xml.XPath.XDocument" Version="$(SystemXmlXPathXDocumentVersion)" />
</ItemGroup>
<ItemGroup>
<Compile Remove="ProvideRoslynBindingRedirection.cs" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.CodeAnalysis;
namespace Roslyn.Utilities
{
internal static class FilePathUtilities
{
public static bool IsRelativePath(string basePath, string path)
{
return path.StartsWith(basePath, StringComparison.OrdinalIgnoreCase);
}
public static string GetRelativePath(string basePath, string path)
{
if (IsRelativePath(basePath, path))
{
var relativePath = path.Substring(basePath.Length);
while (relativePath.Length > 0 && PathUtilities.IsDirectorySeparator(relativePath[0]))
{
relativePath = relativePath.Substring(1);
}
return relativePath;
}
return path;
}
internal static void RequireAbsolutePath(string path, string argumentName)
{
if (path == null)
{
throw new ArgumentNullException(argumentName);
}
if (!PathUtilities.IsAbsolute(path))
{
throw new ArgumentException(WorkspacesResources.Absolute_path_expected, argumentName);
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Composition;
using System.Diagnostics;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host.Mef;
namespace Microsoft.CodeAnalysis.Host
{
[ExportWorkspaceServiceFactory(typeof(IMetadataService), ServiceLayer.Default), Shared]
internal sealed class MetadataServiceFactory : IWorkspaceServiceFactory
{
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
return new Service(workspaceServices.GetService<IDocumentationProviderService>());
}
private sealed class Service : IMetadataService
{
private readonly IDocumentationProviderService documentationService;
private readonly Provider provider;
public Service(IDocumentationProviderService documentationService)
{
this.documentationService = documentationService;
this.provider = new Provider(this);
}
public MetadataReferenceProvider GetProvider()
{
return provider;
}
public PortableExecutableReference GetReference(string resolvedPath, MetadataReferenceProperties properties)
{
return MetadataReference.CreateFromFile(resolvedPath, properties, this.documentationService.GetDocumentationProvider(resolvedPath));
}
}
private sealed class Provider : MetadataReferenceProvider
{
private readonly Service service;
internal Provider(Service service)
{
Debug.Assert(service != null);
this.service = service;
}
public override PortableExecutableReference GetReference(string resolvedPath, MetadataReferenceProperties properties)
{
return service.GetReference(resolvedPath, properties);
}
}
}
}
......@@ -117,9 +117,5 @@
<LastGenOutput>WorkspaceDesktopResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Remove="Utilities\FilePathUtilities.cs" />
<Compile Remove="Workspace\Host\Metadata\MetadataServiceFactory.cs" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Utilities;
namespace Microsoft.CodeAnalysis.Services.OptionService
{
internal struct OptionKeyAndLanguage : IEquatable<OptionKeyAndLanguage>
{
public readonly OptionKey OptionKey;
public readonly string Language;
public OptionKeyAndLanguage(OptionKey optionKey, string language)
{
this.OptionKey = optionKey;
this.Language = language;
}
public override bool Equals(object obj)
{
if (obj is OptionKeyAndLanguage)
{
return Equals((OptionKeyAndLanguage)obj);
}
return false;
}
public bool Equals(OptionKeyAndLanguage other)
{
return OptionKey == other.OptionKey && Language == other.Language;
}
public override int GetHashCode()
{
var hash = OptionKey.GetHashCode();
if (Language != null)
{
hash = Hash.Combine(Language.GetHashCode(), hash);
}
return hash;
}
public static bool operator ==(OptionKeyAndLanguage x, OptionKeyAndLanguage y)
{
return x.Equals(y);
}
public static bool operator !=(OptionKeyAndLanguage x, OptionKeyAndLanguage y)
{
return !x.Equals(y);
}
}
}
......@@ -313,9 +313,6 @@
<PackageReference Include="System.Threading.Tasks.Parallel" Version="$(SystemThreadingTasksParallelVersion)" />
<PackageReference Include="System.Threading.Thread" Version="$(SystemThreadingThreadVersion)" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Options\OptionKeyAndLanguage.cs" />
</ItemGroup>
<Import Project="..\..\..\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.UnitTests.TemporaryStorage
{
public class TestTemporaryStorage : ITemporaryStorage
{
private SourceText text;
private Stream stream;
public SourceText ReadText(CancellationToken cancellationToken = default(CancellationToken))
{
Contract.ThrowIfNull(text);
return text;
}
public Task<SourceText> ReadTextAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return Task.FromResult(ReadText(cancellationToken));
}
public void WriteText(SourceText text, CancellationToken cancellationToken = default(CancellationToken))
{
Contract.ThrowIfTrue(text != null || stream != null);
this.text = text;
}
public Task WriteTextAsync(SourceText text, CancellationToken cancellationToken = default(CancellationToken))
{
WriteText(text, cancellationToken);
return SpecializedTasks.EmptyTask;
}
public Stream ReadStream(CancellationToken cancellationToken = default(CancellationToken))
{
Contract.ThrowIfNull(stream);
return stream;
}
public Task<Stream> ReadStreamAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return Task.FromResult(ReadStream(cancellationToken));
}
public void WriteStream(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
Contract.ThrowIfTrue(text != null || stream != null);
this.stream = stream;
}
public Task WriteStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
WriteStream(stream, cancellationToken);
return SpecializedTasks.EmptyTask;
}
public void Dispose()
{
}
}
}
......@@ -94,8 +94,5 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Compile Remove="Host\WorkspaceServices\TemporaryStorage\TestTemporaryStorage.cs" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
......@@ -73,8 +73,5 @@
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Extensions\SubstituteTypesVisitor.vb" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis.Compilers
Imports Microsoft.CodeAnalysis.Compilers.Common
Imports Microsoft.CodeAnalysis.Compilers.VisualBasic
Imports Microsoft.CodeAnalysis.Text
Namespace Microsoft.CodeAnalysis.Services.Editor.VisualBasic.Extensions
Class SubstituteTypesVisitor(Of TType1 As TypeSymbol, TType2 As TypeSymbol)
Inherits SymbolVisitor(Of Object, TypeSymbol)
Private ReadOnly compilation As Compilation
Private ReadOnly map As IDictionary(Of TType1, TType2)
Friend Sub New(compilation As Compilation, map As IDictionary(Of TType1, TType2))
Me.compilation = compilation
Me.map = map
End Sub
Private Function VisitType(symbol As TypeSymbol, argument As Object) As TypeSymbol
Dim converted As TType2 = Nothing
If TypeOf symbol Is TType1 AndAlso map.TryGetValue(DirectCast(symbol, TType1), converted) Then
Return converted
End If
Return symbol
End Function
Public Overrides Function VisitTypeParameter(symbol As TypeParameterSymbol, argument As Object) As TypeSymbol
Return VisitType(symbol, argument)
End Function
Public Overrides Function VisitErrorType(symbol As ErrorTypeSymbol, argument As Object) As TypeSymbol
Return VisitType(symbol, argument)
End Function
Public Overrides Function VisitNamedType(symbol As NamedTypeSymbol, argument As Object) As TypeSymbol
If symbol.TypeArguments.Count = 0 Then
Return symbol
End If
Dim substitutedArguments = symbol.TypeArguments.[Select](Function(t) Visit(t)).ToArray()
Return (DirectCast(symbol.OriginalDefinition, NamedTypeSymbol)).Construct(substitutedArguments)
End Function
Public Overrides Function VisitArrayType(symbol As ArrayTypeSymbol, argument As Object) As TypeSymbol
Return compilation.CreateArrayTypeSymbol(Visit(symbol.ElementType), symbol.Rank)
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册