提交 257c9eba 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #15118 from CyrusNajmabadi/generatedCode

Share 'generated-code' logic between the compiler and IDE.
......@@ -31,6 +31,7 @@
</Content>
<Compile Include="DiagnosticAnalyzer\AnalyzerManager.AnalyzerExecutionContext.cs" />
<Compile Include="InternalUtilities\CommandLineUtilities.cs" />
<Compile Include="InternalUtilities\GeneratedCodeUtilities.cs" />
<Compile Include="InternalUtilities\NoThrowStreamDisposer.cs" />
<Compile Include="InternalUtilities\OrderedMultiDictionary.cs" />
<Compile Include="InternalUtilities\PlatformInformation.cs" />
......@@ -86,7 +87,6 @@
<Compile Include="DiagnosticAnalyzer\SourceTextValueProvider.cs" />
<Compile Include="DiagnosticAnalyzer\CompilationAnalysisValueProviderFactory.cs" />
<Compile Include="DiagnosticAnalyzer\CompilationAnalysisValueProvider.cs" />
<Compile Include="DiagnosticAnalyzer\AnalyzerDriver.GeneratedCodeUtilities.cs" />
<Compile Include="DiagnosticAnalyzer\AnalyzerDriver.CompilationData.cs" />
<Compile Include="DiagnosticAnalyzer\AnalysisContextInfo.cs" />
<Compile Include="DiagnosticAnalyzer\AnalysisValueProvider.cs" />
......
......@@ -4,17 +4,16 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis;
namespace Microsoft.CodeAnalysis.Diagnostics
namespace Roslyn.Utilities
{
internal abstract partial class AnalyzerDriver : IDisposable
{
private static class GeneratedCodeUtilities
internal static class GeneratedCodeUtilities
{
private static readonly string[] s_autoGeneratedStrings = new[] { "<autogenerated", "<auto-generated" };
internal static bool IsGeneratedSymbolWithGeneratedCodeAttribute(ISymbol symbol, INamedTypeSymbol generatedCodeAttribute)
internal static bool IsGeneratedSymbolWithGeneratedCodeAttribute(
ISymbol symbol, INamedTypeSymbol generatedCodeAttribute)
{
Debug.Assert(symbol != null);
Debug.Assert(generatedCodeAttribute != null);
......@@ -34,53 +33,42 @@ internal static bool IsGeneratedSymbolWithGeneratedCodeAttribute(ISymbol symbol,
return symbol.ContainingSymbol != null && IsGeneratedSymbolWithGeneratedCodeAttribute(symbol.ContainingSymbol, generatedCodeAttribute);
}
internal static bool IsGeneratedCode(SyntaxTree tree, Func<SyntaxTrivia, bool> isComment, CancellationToken cancellationToken)
internal static bool IsGeneratedCode(
SyntaxTree tree, Func<SyntaxTrivia, bool> isComment, CancellationToken cancellationToken)
{
if (IsGeneratedCodeFile(tree.FilePath))
{
return true;
}
if (BeginsWithAutoGeneratedComment(tree, isComment, cancellationToken))
{
return true;
}
return false;
return IsGeneratedCodeFile(tree.FilePath) ||
BeginsWithAutoGeneratedComment(tree, isComment, cancellationToken);
}
private static bool IsGeneratedCodeFile(string filePath)
{
if (string.IsNullOrEmpty(filePath))
if (!string.IsNullOrEmpty(filePath))
{
return false;
}
var fileName = PathUtilities.GetFileName(filePath);
if (fileName.StartsWith("TemporaryGeneratedFile_", StringComparison.OrdinalIgnoreCase))
{
return true;
}
var extension = PathUtilities.GetExtension(fileName);
if (string.IsNullOrEmpty(extension))
{
return false;
}
var fileName = PathUtilities.GetFileName(filePath);
if (fileName.StartsWith("TemporaryGeneratedFile_", StringComparison.OrdinalIgnoreCase))
{
return true;
}
var fileNameWithoutExtension = PathUtilities.GetFileName(filePath, includeExtension: false);
if (fileNameWithoutExtension.EndsWith(".designer", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".generated", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".g", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".g.i", StringComparison.OrdinalIgnoreCase))
{
return true;
var extension = PathUtilities.GetExtension(fileName);
if (!string.IsNullOrEmpty(extension))
{
var fileNameWithoutExtension = PathUtilities.GetFileName(filePath, includeExtension: false);
if (fileNameWithoutExtension.EndsWith(".designer", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".generated", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".g", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".g.i", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
return false;
}
private static bool BeginsWithAutoGeneratedComment(SyntaxTree tree, Func<SyntaxTrivia, bool> isComment, CancellationToken cancellationToken)
private static bool BeginsWithAutoGeneratedComment(
SyntaxTree tree, Func<SyntaxTrivia, bool> isComment, CancellationToken cancellationToken)
{
var root = tree.GetRoot(cancellationToken);
if (root.HasLeadingTrivia)
......@@ -110,5 +98,4 @@ private static bool BeginsWithAutoGeneratedComment(SyntaxTree tree, Func<SyntaxT
return false;
}
}
}
}
}
\ No newline at end of file
......@@ -20,7 +20,8 @@ internal abstract class AbstractNavigationBarItemService : INavigationBarItemSer
public abstract void NavigateToItem(Document document, NavigationBarItem item, ITextView textView, CancellationToken cancellationToken);
public void NavigateToSymbolItem(Document document, NavigationBarSymbolItem item, CancellationToken cancellationToken)
public void NavigateToSymbolItem(
Document document, NavigationBarSymbolItem item, CancellationToken cancellationToken)
{
var symbolNavigationService = document.Project.Solution.Workspace.Services.GetService<ISymbolNavigationService>();
......@@ -31,7 +32,7 @@ public void NavigateToSymbolItem(Document document, NavigationBarSymbolItem item
if (symbol != null &&
!(symbol is ITypeSymbol) &&
!symbol.IsConstructor() &&
symbolNavigationService.TrySymbolNavigationNotify(symbol, document.Project.Solution))
symbolNavigationService.TrySymbolNavigationNotify(symbol, document.Project.Solution, cancellationToken))
{
return;
}
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.FindUsages;
using Microsoft.CodeAnalysis.Editor.Host;
......@@ -59,7 +60,7 @@ public bool TryFindReferences(Document document, int position, IWaitContext wait
var cancellationToken = waitContext.CancellationToken;
var result = this.FindReferencedSymbolsAsync(document, position, waitContext).WaitAndGetResult(cancellationToken);
return TryDisplayReferences(result);
return TryDisplayReferences(result, cancellationToken);
}
private bool TryDisplayReferences(IEnumerable<INavigableItem> result)
......@@ -77,14 +78,16 @@ private bool TryDisplayReferences(IEnumerable<INavigableItem> result)
return false;
}
private bool TryDisplayReferences(Tuple<IEnumerable<ReferencedSymbol>, Solution> result)
private bool TryDisplayReferences(
Tuple<IEnumerable<ReferencedSymbol>, Solution> result,
CancellationToken cancellationToken)
{
if (result != null && result.Item1 != null)
{
var solution = result.Item2;
var factory = solution.Workspace.Services.GetService<IDefinitionsAndReferencesFactory>();
var definitionsAndReferences = factory.CreateDefinitionsAndReferences(
solution, result.Item1, includeHiddenLocations: false);
solution, result.Item1, includeHiddenLocations: false, cancellationToken: cancellationToken);
foreach (var presenter in _referenceSymbolPresenters)
{
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.FindUsages;
......@@ -85,12 +86,13 @@ public async Task OnReferenceFoundAsync(SymbolAndProjectId definition, Reference
}
}
public async Task CallThirdPartyExtensionsAsync()
public async Task CallThirdPartyExtensionsAsync(CancellationToken cancellationToken)
{
var factory = _solution.Workspace.Services.GetService<IDefinitionsAndReferencesFactory>();
foreach (var definition in _definitionToItem.Keys)
{
var item = factory.GetThirdPartyDefinitionItem(_solution, definition);
var item = factory.GetThirdPartyDefinitionItem(
_solution, definition, cancellationToken);
if (item != null)
{
// ConfigureAwait(true) because we want to come back on the
......
......@@ -56,7 +56,8 @@ public async Task FindImplementationsAsync(Document document, int position, IFin
// After the FAR engine is done call into any third party extensions to see
// if they want to add results.
await findReferencesProgress.CallThirdPartyExtensionsAsync().ConfigureAwait(true);
await findReferencesProgress.CallThirdPartyExtensionsAsync(
context.CancellationToken).ConfigureAwait(true);
}
private async Task<ProgressAdapter> FindReferencesWorkerAsync(
......
......@@ -50,13 +50,14 @@ private async Task<ISymbol> FindSymbolAsync(Document document, int position, Can
return FindRelatedExplicitlyDeclaredSymbol(symbol, semanticModel.Compilation);
}
public async Task<IEnumerable<INavigableItem>> FindDefinitionsAsync(Document document, int position, CancellationToken cancellationToken)
public async Task<IEnumerable<INavigableItem>> FindDefinitionsAsync(
Document document, int position, CancellationToken cancellationToken)
{
var symbol = await FindSymbolAsync(document, position, cancellationToken).ConfigureAwait(false);
// Try to compute source definitions from symbol.
var items = symbol != null
? NavigableItemFactory.GetItemsFromPreferredSourceLocations(document.Project.Solution, symbol, displayTaggedParts: null)
? NavigableItemFactory.GetItemsFromPreferredSourceLocations(document.Project.Solution, symbol, displayTaggedParts: null, cancellationToken: cancellationToken)
: null;
// realize the list here so that the consumer await'ing the result doesn't lazily cause
......
......@@ -40,10 +40,15 @@ internal static class GoToDefinitionHelpers
// We can't go to the definition of the alias, so use the target type.
var solution = project.Solution;
if (symbol is IAliasSymbol &&
NavigableItemFactory.GetPreferredSourceLocations(solution, symbol).All(l => project.Solution.GetDocument(l.SourceTree) == null))
if (symbol is IAliasSymbol)
{
symbol = ((IAliasSymbol)symbol).Target;
var sourceLocations = NavigableItemFactory.GetPreferredSourceLocations(
solution, symbol, cancellationToken);
if (sourceLocations.All(l => project.Solution.GetDocument(l.SourceTree) == null))
{
symbol = ((IAliasSymbol)symbol).Target;
}
}
var definition = SymbolFinder.FindSourceDefinitionAsync(symbol, solution, cancellationToken).WaitAndGetResult(cancellationToken);
......@@ -52,10 +57,10 @@ internal static class GoToDefinitionHelpers
symbol = definition ?? symbol;
var definitions = ArrayBuilder<DefinitionItem>.GetInstance();
if (thirdPartyNavigationAllowed )
if (thirdPartyNavigationAllowed)
{
var factory = solution.Workspace.Services.GetService<IDefinitionsAndReferencesFactory>();
var thirdPartyItem = factory?.GetThirdPartyDefinitionItem(solution, symbol);
var thirdPartyItem = factory?.GetThirdPartyDefinitionItem(solution, symbol, cancellationToken);
definitions.AddIfNotNull(thirdPartyItem);
}
......@@ -92,12 +97,13 @@ internal static class GoToDefinitionHelpers
}
}
private static bool TryThirdPartyNavigation(ISymbol symbol, Solution solution)
private static bool TryThirdPartyNavigation(
ISymbol symbol, Solution solution, CancellationToken cancellationToken)
{
var symbolNavigationService = solution.Workspace.Services.GetService<ISymbolNavigationService>();
// Notify of navigation so third parties can intercept the navigation
return symbolNavigationService.TrySymbolNavigationNotify(symbol, solution);
return symbolNavigationService.TrySymbolNavigationNotify(symbol, solution, cancellationToken);
}
}
}
\ No newline at end of file
......@@ -25,7 +25,10 @@ private PeekableItemFactory(IMetadataAsSourceFileService metadataAsSourceFileSer
_metadataAsSourceFileService = metadataAsSourceFileService;
}
public async Task<IEnumerable<IPeekableItem>> GetPeekableItemsAsync(ISymbol symbol, Project project, IPeekResultFactory peekResultFactory, CancellationToken cancellationToken)
public async Task<IEnumerable<IPeekableItem>> GetPeekableItemsAsync(
ISymbol symbol, Project project,
IPeekResultFactory peekResultFactory,
CancellationToken cancellationToken)
{
if (symbol == null)
{
......@@ -57,7 +60,9 @@ public async Task<IEnumerable<IPeekableItem>> GetPeekableItemsAsync(ISymbol symb
var symbolNavigationService = solution.Workspace.Services.GetService<ISymbolNavigationService>();
if (symbolNavigationService.WouldNavigateToSymbol(symbol, solution, out var filePath, out var lineNumber, out var charOffset))
if (symbolNavigationService.WouldNavigateToSymbol(
symbol, solution, cancellationToken,
out var filePath, out var lineNumber, out var charOffset))
{
var position = new LinePosition(lineNumber, charOffset);
results.Add(new ExternalFilePeekableItem(new FileLinePositionSpan(filePath, position, position), PredefinedPeekRelationships.Definitions, peekResultFactory));
......
......@@ -13,7 +13,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers
Public ReadOnly Catalog As ComposableCatalog = TestExportProvider.MinimumCatalogWithCSharpAndVisualBasic.WithParts(
GetType(MockDocumentNavigationServiceFactory),
GetType(DefaultSymbolNavigationServiceFactory),
GetType(GeneratedCodeRecognitionServiceFactory))
GetType(GeneratedCodeRecognitionService))
Public ReadOnly ExportProvider As ExportProvider = MinimalTestExportProvider.CreateExportProvider(Catalog)
......
......@@ -45,14 +45,19 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Utilities
Return True
End Function
Public Function TrySymbolNavigationNotify(symbol As ISymbol, solution As Solution) As Boolean Implements ISymbolNavigationService.TrySymbolNavigationNotify
Public Function TrySymbolNavigationNotify(symbol As ISymbol,
solution As Solution,
cancellationToken As CancellationToken) As Boolean Implements ISymbolNavigationService.TrySymbolNavigationNotify
Me.TrySymbolNavigationNotifyProvidedSymbol = symbol
Me.TrySymbolNavigationNotifyProvidedSolution = solution
Return TrySymbolNavigationNotifyReturnValue
End Function
Public Function WouldNavigateToSymbol(symbol As ISymbol, solution As Solution, ByRef filePath As String, ByRef lineNumber As Integer, ByRef charOffset As Integer) As Boolean Implements ISymbolNavigationService.WouldNavigateToSymbol
Public Function WouldNavigateToSymbol(symbol As ISymbol,
solution As Solution,
cancellationToken As CancellationToken,
ByRef filePath As String, ByRef lineNumber As Integer, ByRef charOffset As Integer) As Boolean Implements ISymbolNavigationService.WouldNavigateToSymbol
Me.WouldNavigateToSymbolProvidedSymbol = symbol
Me.WouldNavigateToSymbolProvidedSolution = solution
......
......@@ -23,7 +23,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
return;
}
if (document.IsGeneratedCode())
if (document.IsGeneratedCode(cancellationToken))
{
return;
}
......
......@@ -5,6 +5,7 @@
using System.Composition;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Host;
......@@ -17,16 +18,19 @@ namespace Microsoft.CodeAnalysis.FindUsages
internal interface IDefinitionsAndReferencesFactory : IWorkspaceService
{
DefinitionsAndReferences CreateDefinitionsAndReferences(
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols, bool includeHiddenLocations);
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols,
bool includeHiddenLocations, CancellationToken cancellationToken);
DefinitionItem GetThirdPartyDefinitionItem(Solution solution, ISymbol definition);
DefinitionItem GetThirdPartyDefinitionItem(
Solution solution, ISymbol definition, CancellationToken cancellationToken);
}
[ExportWorkspaceService(typeof(IDefinitionsAndReferencesFactory)), Shared]
internal class DefaultDefinitionsAndReferencesFactory : IDefinitionsAndReferencesFactory
{
public DefinitionsAndReferences CreateDefinitionsAndReferences(
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols, bool includeHiddenLocations)
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols,
bool includeHiddenLocations, CancellationToken cancellationToken)
{
var definitions = ArrayBuilder<DefinitionItem>.GetInstance();
var references = ArrayBuilder<SourceReferenceItem>.GetInstance();
......@@ -40,7 +44,7 @@ internal class DefaultDefinitionsAndReferencesFactory : IDefinitionsAndReference
{
ProcessReferencedSymbol(
solution, referencedSymbol, definitions, references,
includeHiddenLocations, uniqueLocations);
includeHiddenLocations, uniqueLocations,cancellationToken);
}
return new DefinitionsAndReferences(
......@@ -88,7 +92,8 @@ private static int GetPrecedence(ReferencedSymbol referencedSymbol)
ArrayBuilder<DefinitionItem> definitions,
ArrayBuilder<SourceReferenceItem> references,
bool includeHiddenLocations,
HashSet<DocumentSpan> uniqueSpans)
HashSet<DocumentSpan> uniqueSpans,
CancellationToken cancellationToken)
{
// See if this is a symbol we even want to present to the user. If not,
// ignore it entirely (including all its reference locations).
......@@ -109,7 +114,8 @@ private static int GetPrecedence(ReferencedSymbol referencedSymbol)
// Finally, see if there are any third parties that want to add their
// own result to our collection.
var thirdPartyItem = GetThirdPartyDefinitionItem(solution, referencedSymbol.Definition);
var thirdPartyItem = GetThirdPartyDefinitionItem(
solution, referencedSymbol.Definition, cancellationToken);
if (thirdPartyItem != null)
{
definitions.Add(thirdPartyItem);
......@@ -121,7 +127,7 @@ private static int GetPrecedence(ReferencedSymbol referencedSymbol)
/// results to the results found by the FindReferences engine.
/// </summary>
public virtual DefinitionItem GetThirdPartyDefinitionItem(
Solution solution, ISymbol definition)
Solution solution, ISymbol definition, CancellationToken cancellationToken)
{
return null;
}
......
......@@ -12,12 +12,14 @@ public bool TryNavigateToSymbol(ISymbol symbol, Project project, OptionSet optio
return false;
}
public bool TrySymbolNavigationNotify(ISymbol symbol, Solution solution)
public bool TrySymbolNavigationNotify(ISymbol symbol, Solution solution, CancellationToken cancellationToken)
{
return false;
}
public bool WouldNavigateToSymbol(ISymbol symbol, Solution solution, out string filePath, out int lineNumber, out int charOffset)
public bool WouldNavigateToSymbol(
ISymbol symbol, Solution solution, CancellationToken cancellationToken,
out string filePath, out int lineNumber, out int charOffset)
{
filePath = null;
lineNumber = 0;
......
......@@ -21,9 +21,11 @@ internal interface ISymbolNavigationService : IWorkspaceService
/// <returns>True if the navigation was handled, indicating that the caller should not
/// perform the navigation.</returns>
bool TrySymbolNavigationNotify(ISymbol symbol, Solution solution);
bool TrySymbolNavigationNotify(ISymbol symbol, Solution solution, CancellationToken cancellationToken);
/// <returns>True if the navigation would be handled.</returns>
bool WouldNavigateToSymbol(ISymbol symbol, Solution solution, out string filePath, out int lineNumber, out int charOffset);
bool WouldNavigateToSymbol(
ISymbol symbol, Solution solution, CancellationToken cancellationToken,
out string filePath, out int lineNumber, out int charOffset);
}
}
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.GeneratedCodeRecognition;
using Microsoft.CodeAnalysis.LanguageServices;
......@@ -29,15 +30,16 @@ public static INavigableItem GetItemFromDeclaredSymbolInfo(DeclaredSymbolInfo de
public static IEnumerable<INavigableItem> GetItemsFromPreferredSourceLocations(
Solution solution,
ISymbol symbol,
ImmutableArray<TaggedText>? displayTaggedParts)
ImmutableArray<TaggedText>? displayTaggedParts,
CancellationToken cancellationToken)
{
var locations = GetPreferredSourceLocations(solution, symbol);
var locations = GetPreferredSourceLocations(solution, symbol, cancellationToken);
return locations.Select(loc => GetItemFromSymbolLocation(
solution, symbol, loc, displayTaggedParts));
}
public static IEnumerable<Location> GetPreferredSourceLocations(
Solution solution, ISymbol symbol)
Solution solution, ISymbol symbol, CancellationToken cancellationToken)
{
// Prefer non-generated source locations over generated ones.
......@@ -46,7 +48,7 @@ public static INavigableItem GetItemFromDeclaredSymbolInfo(DeclaredSymbolInfo de
var candidateLocationGroups = from c in sourceLocations
let doc = solution.GetDocument(c.SourceTree)
where doc != null
group c by doc.IsGeneratedCode();
group c by doc.IsGeneratedCode(cancellationToken);
var generatedSourceLocations = candidateLocationGroups.SingleOrDefault(g => g.Key) ?? SpecializedCollections.EmptyEnumerable<Location>();
var nonGeneratedSourceLocations = candidateLocationGroups.SingleOrDefault(g => !g.Key) ?? SpecializedCollections.EmptyEnumerable<Location>();
......@@ -66,13 +68,16 @@ private static IEnumerable<Location> GetPreferredSourceLocations(ISymbol symbol)
: locations.Where(loc => loc.IsInSource);
}
public static IEnumerable<INavigableItem> GetPreferredNavigableItems(Solution solution, IEnumerable<INavigableItem> navigableItems)
public static IEnumerable<INavigableItem> GetPreferredNavigableItems(
Solution solution,
IEnumerable<INavigableItem> navigableItems,
CancellationToken cancellationToken)
{
navigableItems = navigableItems.Where(n => n.Document != null);
var hasNonGeneratedCodeItem = navigableItems.Any(n => !n.Document.IsGeneratedCode());
var hasNonGeneratedCodeItem = navigableItems.Any(n => !n.Document.IsGeneratedCode(cancellationToken));
return hasNonGeneratedCodeItem
? navigableItems.Where(n => !n.Document.IsGeneratedCode())
: navigableItems.Where(n => n.Document.IsGeneratedCode());
? navigableItems.Where(n => !n.Document.IsGeneratedCode(cancellationToken))
: navigableItems.Where(n => n.Document.IsGeneratedCode(cancellationToken));
}
public static ImmutableArray<TaggedText> GetSymbolDisplayTaggedParts(Project project, ISymbol symbol)
......@@ -121,4 +126,4 @@ private static SymbolDisplayFormat GetSymbolDisplayFormat(ISymbol symbol)
SymbolDisplayMemberOptions.IncludeExplicitInterface |
SymbolDisplayMemberOptions.IncludeParameters);
}
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@
using System.Collections.Immutable;
using System.Composition;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.FindUsages;
......@@ -30,10 +31,12 @@ public VisualStudioDefinitionsAndReferencesFactory(SVsServiceProvider servicePro
}
public override DefinitionItem GetThirdPartyDefinitionItem(
Solution solution, ISymbol definition)
Solution solution, ISymbol definition, CancellationToken cancellationToken)
{
var symbolNavigationService = solution.Workspace.Services.GetService<ISymbolNavigationService>();
if (!symbolNavigationService.WouldNavigateToSymbol(definition, solution, out var filePath, out var lineNumber, out var charOffset))
if (!symbolNavigationService.WouldNavigateToSymbol(
definition, solution, cancellationToken,
out var filePath, out var lineNumber, out var charOffset))
{
return null;
}
......
......@@ -5,6 +5,7 @@
using System.IO;
using System.Linq;
using System.Security;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.GeneratedCodeRecognition;
using Microsoft.CodeAnalysis.GenerateType;
......@@ -507,45 +508,43 @@ public int ProjectSelectIndex
private Project _previouslyPopulatedProject = null;
private List<DocumentSelectItem> _previouslyPopulatedDocumentList = null;
public IEnumerable<DocumentSelectItem> DocumentList
public IEnumerable<DocumentSelectItem> GetDocumentList(CancellationToken cancellationToken)
{
get
if (_previouslyPopulatedProject == _selectedProject)
{
if (_previouslyPopulatedProject == _selectedProject)
{
return _previouslyPopulatedDocumentList;
}
_previouslyPopulatedProject = _selectedProject;
_previouslyPopulatedDocumentList = new List<DocumentSelectItem>();
return _previouslyPopulatedDocumentList;
}
// Check for the current project
if (_selectedProject == _document.Project)
{
// populate the current document
_previouslyPopulatedDocumentList.Add(new DocumentSelectItem(_document, "<Current File>"));
_previouslyPopulatedProject = _selectedProject;
_previouslyPopulatedDocumentList = new List<DocumentSelectItem>();
// Set the initial selected Document
this.SelectedDocument = _document;
// Check for the current project
if (_selectedProject == _document.Project)
{
// populate the current document
_previouslyPopulatedDocumentList.Add(new DocumentSelectItem(_document, "<Current File>"));
// Populate the rest of the documents for the project
_previouslyPopulatedDocumentList.AddRange(_document.Project.Documents
.Where(d => d != _document && !d.IsGeneratedCode())
.Select(d => new DocumentSelectItem(d)));
}
else
{
_previouslyPopulatedDocumentList.AddRange(_selectedProject.Documents
.Where(d => !d.IsGeneratedCode())
.Select(d => new DocumentSelectItem(d)));
// Set the initial selected Document
this.SelectedDocument = _document;
this.SelectedDocument = _selectedProject.Documents.FirstOrDefault();
}
// Populate the rest of the documents for the project
_previouslyPopulatedDocumentList.AddRange(_document.Project.Documents
.Where(d => d != _document && !d.IsGeneratedCode(cancellationToken))
.Select(d => new DocumentSelectItem(d)));
}
else
{
_previouslyPopulatedDocumentList.AddRange(_selectedProject.Documents
.Where(d => !d.IsGeneratedCode(cancellationToken))
.Select(d => new DocumentSelectItem(d)));
this.IsExistingFileEnabled = _previouslyPopulatedDocumentList.Count == 0 ? false : true;
this.IsNewFile = this.IsExistingFileEnabled ? this.IsNewFile : true;
return _previouslyPopulatedDocumentList;
this.SelectedDocument = _selectedProject.Documents.FirstOrDefault();
}
this.IsExistingFileEnabled = _previouslyPopulatedDocumentList.Count == 0 ? false : true;
this.IsNewFile = this.IsExistingFileEnabled ? this.IsNewFile : true;
return _previouslyPopulatedDocumentList;
}
private bool _isExistingFileEnabled = true;
......
......@@ -81,7 +81,8 @@ public void NavigateTo(GraphObject graphObject)
}
}
private void NavigateOnForegroundThread(SourceLocation sourceLocation, SymbolKey? symbolId, Project project, Document document)
private void NavigateOnForegroundThread(
SourceLocation sourceLocation, SymbolKey? symbolId, Project project, Document document)
{
AssertIsForeground();
......@@ -95,7 +96,7 @@ private void NavigateOnForegroundThread(SourceLocation sourceLocation, SymbolKey
if (symbol != null &&
!(symbol is ITypeSymbol) &&
!symbol.IsConstructor() &&
symbolNavigationService.TrySymbolNavigationNotify(symbol, project.Solution))
symbolNavigationService.TrySymbolNavigationNotify(symbol, project.Solution, CancellationToken.None))
{
return;
}
......
......@@ -118,4 +118,4 @@ public PortableExecutableReference CreatePortableExecutableReference(string file
return this.Services.GetService<IMetadataService>().GetReference(filePath, properties);
}
}
}
}
\ No newline at end of file
......@@ -8,7 +8,6 @@
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Editor.Implementation.Structure;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.GeneratedCodeRecognition;
using Microsoft.CodeAnalysis.Navigation;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
......@@ -24,7 +23,6 @@
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Roslyn.Utilities;
using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
namespace Microsoft.VisualStudio.LanguageServices.Implementation
{
......@@ -149,15 +147,18 @@ public bool TryNavigateToSymbol(ISymbol symbol, Project project, OptionSet optio
return true;
}
public bool TrySymbolNavigationNotify(ISymbol symbol, Solution solution)
public bool TrySymbolNavigationNotify(ISymbol symbol, Solution solution, CancellationToken cancellationToken)
{
return TryNotifyForSpecificSymbol(symbol, solution);
return TryNotifyForSpecificSymbol(symbol, solution, cancellationToken);
}
private bool TryNotifyForSpecificSymbol(ISymbol symbol, Solution solution)
private bool TryNotifyForSpecificSymbol(
ISymbol symbol, Solution solution, CancellationToken cancellationToken)
{
AssertIsForeground();
if (!TryGetNavigationAPIRequiredArguments(symbol, solution, out var hierarchy, out var itemID, out var navigationNotify, out var rqname))
if (!TryGetNavigationAPIRequiredArguments(
symbol, solution, cancellationToken,
out var hierarchy, out var itemID, out var navigationNotify, out var rqname))
{
return false;
}
......@@ -176,16 +177,19 @@ private bool TryNotifyForSpecificSymbol(ISymbol symbol, Solution solution)
return false;
}
public bool WouldNavigateToSymbol(ISymbol symbol, Solution solution, out string filePath, out int lineNumber, out int charOffset)
public bool WouldNavigateToSymbol(
ISymbol symbol, Solution solution, CancellationToken cancellationToken,
out string filePath, out int lineNumber, out int charOffset)
{
if (WouldNotifyToSpecificSymbol(symbol, solution, out filePath, out lineNumber, out charOffset))
if (WouldNotifyToSpecificSymbol(symbol, solution, cancellationToken, out filePath, out lineNumber, out charOffset))
{
return true;
}
// If the symbol being considered is a constructor and no third parties choose to
// navigate to the constructor, then try the constructor's containing type.
if (symbol.IsConstructor() && WouldNotifyToSpecificSymbol(symbol.ContainingType, solution, out filePath, out lineNumber, out charOffset))
if (symbol.IsConstructor() && WouldNotifyToSpecificSymbol(
symbol.ContainingType, solution, cancellationToken, out filePath, out lineNumber, out charOffset))
{
return true;
}
......@@ -196,14 +200,18 @@ public bool WouldNavigateToSymbol(ISymbol symbol, Solution solution, out string
return false;
}
public bool WouldNotifyToSpecificSymbol(ISymbol symbol, Solution solution, out string filePath, out int lineNumber, out int charOffset)
public bool WouldNotifyToSpecificSymbol(
ISymbol symbol, Solution solution, CancellationToken cancellationToken,
out string filePath, out int lineNumber, out int charOffset)
{
AssertIsForeground();
filePath = null;
lineNumber = 0;
charOffset = 0;
if (!TryGetNavigationAPIRequiredArguments(symbol, solution, out var hierarchy, out var itemID, out var navigationNotify, out var rqname))
if (!TryGetNavigationAPIRequiredArguments(
symbol, solution, cancellationToken,
out var hierarchy, out var itemID, out var navigationNotify, out var rqname))
{
return false;
}
......@@ -233,6 +241,7 @@ public bool WouldNotifyToSpecificSymbol(ISymbol symbol, Solution solution, out s
private bool TryGetNavigationAPIRequiredArguments(
ISymbol symbol,
Solution solution,
CancellationToken cancellationToken,
out IVsHierarchy hierarchy,
out uint itemID,
out IVsSymbolicNavigationNotify navigationNotify,
......@@ -266,7 +275,7 @@ public bool WouldNotifyToSpecificSymbol(ISymbol symbol, Solution solution, out s
// documents we consider to be "generated" to give external language services the best
// chance of participating.
var generatedDocuments = documents.Where(d => d.IsGeneratedCode());
var generatedDocuments = documents.Where(d => d.IsGeneratedCode(cancellationToken));
var documentToUse = generatedDocuments.FirstOrDefault() ?? documents.First();
if (!TryGetVsHierarchyAndItemId(documentToUse, out hierarchy, out itemID))
......@@ -310,4 +319,4 @@ private IVsRunningDocumentTable GetRunningDocumentTable()
return runningDocumentTable;
}
}
}
}
\ No newline at end of file
......@@ -600,7 +600,8 @@ protected EnvDTE.vsCMElement GetElementKind(ITypeSymbol typeSymbol)
}
}
protected bool TryGetElementFromSource(CodeModelState state, Project project, ITypeSymbol typeSymbol, out EnvDTE.CodeElement element)
protected bool TryGetElementFromSource(
CodeModelState state, Project project, ITypeSymbol typeSymbol, out EnvDTE.CodeElement element)
{
element = null;
......@@ -629,7 +630,7 @@ protected bool TryGetElementFromSource(CodeModelState state, Project project, IT
{
var document = project.GetDocument(location.SourceTree);
if (document.IsGeneratedCode() == false)
if (!document.IsGeneratedCode(CancellationToken.None))
{
chosenLocation = location;
chosenDocumentId = document.Id;
......
......@@ -142,7 +142,7 @@ internal override IInvisibleEditor OpenInvisibleEditor(IVisualStudioHostDocument
if (this.CurrentSolution.ContainsDocument(hostDocument.Id))
{
// Disable undo on generated documents
needsUndoDisabled = this.CurrentSolution.GetDocument(hostDocument.Id).IsGeneratedCode();
needsUndoDisabled = this.CurrentSolution.GetDocument(hostDocument.Id).IsGeneratedCode(CancellationToken.None);
}
else
{
......@@ -232,7 +232,8 @@ public override bool TryFindAllReferences(ISymbol symbol, Project project, Cance
{
var service = this.Services.GetService<IDefinitionsAndReferencesFactory>();
var definitionsAndReferences = service.CreateDefinitionsAndReferences(
solution, referencedSymbols, includeHiddenLocations: false);
solution, referencedSymbols,
includeHiddenLocations: false, cancellationToken: CancellationToken.None);
foreach (var presenter in _referencedSymbolsPresenters)
{
......
......@@ -151,7 +151,8 @@ using System.Threading;
Dim factory = workspace.Services.GetService(Of IDefinitionsAndReferencesFactory)
Dim definitionsAndReferences = factory.CreateDefinitionsAndReferences(
workspace.CurrentSolution, result, includeHiddenLocations:=False)
workspace.CurrentSolution, result,
includeHiddenLocations:=False, cancellationToken:=CancellationToken.None)
Dim findReferencesTree = libraryManager.CreateFindReferencesItems(definitionsAndReferences)
' We cannot control the ordering of top-level nodes in the Find Symbol References window, so do not consider ordering of these items here.
......
......@@ -196,18 +196,17 @@ namespace A
' Only 2 Projects can be selected because CS2 and CS3 will introduce cyclic dependency
Assert.Equal(2, viewModel.ProjectList.Count)
Assert.Equal(2, viewModel.DocumentList.Count)
Assert.Equal(2, viewModel.GetDocumentList(CancellationToken.None).Count)
viewModel.DocumentSelectIndex = 1
Dim projectToSelect = viewModel.ProjectList.Where(Function(p) p.Name = "VB1").Single().Project
Dim monitor = New PropertyChangedTestMonitor(viewModel)
monitor.AddExpectation(Function() viewModel.DocumentList)
' Check to see if the values are reset when there is a change in the project selection
viewModel.SelectedProject = projectToSelect
Assert.Equal(2, viewModel.DocumentList.Count())
Assert.Equal(2, viewModel.GetDocumentList(CancellationToken.None).Count())
Assert.Equal(0, viewModel.DocumentSelectIndex)
Assert.Equal(1, viewModel.ProjectSelectIndex)
......@@ -249,7 +248,7 @@ namespace A
' Check if the option for Existing File is disabled
Assert.Equal(0, viewModel.DocumentList.Count())
Assert.Equal(0, viewModel.GetDocumentList(CancellationToken.None).Count())
Assert.Equal(False, viewModel.IsExistingFileEnabled)
' Select the project CS1 which has documents
......@@ -257,7 +256,7 @@ namespace A
viewModel.SelectedProject = projectToSelect
' Check if the option for Existing File is enabled
Assert.Equal(2, viewModel.DocumentList.Count())
Assert.Equal(2, viewModel.GetDocumentList(CancellationToken.None).Count())
Assert.Equal(True, viewModel.IsExistingFileEnabled)
End Function
......@@ -587,7 +586,7 @@ class Program
Dim viewModel = Await GetViewModelAsync(workspaceXml, LanguageNames.CSharp)
Dim expectedDocuments = {"Test1.cs", "Test2.cs", "AssemblyInfo.cs", "Test3.cs"}
Assert.Equal(expectedDocuments, viewModel.DocumentList.Select(Function(d) d.Document.Name).ToArray())
Assert.Equal(expectedDocuments, viewModel.GetDocumentList(CancellationToken.None).Select(Function(d) d.Document.Name).ToArray())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateType)>
......
......@@ -1602,10 +1602,14 @@ public SeparatedSyntaxList<SyntaxNode> GetArgumentsOfInvocationExpression(Syntax
return ((invocationExpression as InvocationExpressionSyntax)?.ArgumentList.Arguments).Value;
}
public bool IsRegularComment(SyntaxTrivia trivia)
=> trivia.IsRegularComment();
public bool IsDocumentationComment(SyntaxTrivia trivia)
=> trivia.IsDocComment();
public bool IsDocumentationComment(SyntaxNode node)
{
return SyntaxFacts.IsDocumentationCommentTrivia(node.Kind());
}
=> SyntaxFacts.IsDocumentationCommentTrivia(node.Kind());
public bool IsUsingOrExternOrImport(SyntaxNode node)
{
......
......@@ -54,7 +54,9 @@ public abstract class DiagnosticProvider
internal virtual async Task<ImmutableDictionary<Document, ImmutableArray<Diagnostic>>> GetDocumentDiagnosticsToFixWorkerAsync(
FixAllContext fixAllContext)
{
using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, fixAllContext.CancellationToken))
var cancellationToken = fixAllContext.CancellationToken;
using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, cancellationToken))
{
var allDiagnostics = ImmutableArray<Diagnostic>.Empty;
var projectsToFix = ImmutableArray<Project>.Empty;
......@@ -65,7 +67,7 @@ public abstract class DiagnosticProvider
switch (fixAllContext.Scope)
{
case FixAllScope.Document:
if (document != null && !document.IsGeneratedCode())
if (document != null && !document.IsGeneratedCode(cancellationToken))
{
var documentDiagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(document, documentDiagnostics));
......@@ -91,19 +93,19 @@ public abstract class DiagnosticProvider
var tasks = new Task[projectsToFix.Length];
for (int i = 0; i < projectsToFix.Length; i++)
{
fixAllContext.CancellationToken.ThrowIfCancellationRequested();
cancellationToken.ThrowIfCancellationRequested();
var projectToFix = projectsToFix[i];
tasks[i] = Task.Run(async () =>
{
var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false);
foreach (var diagnostic in projectDiagnostics)
{
fixAllContext.CancellationToken.ThrowIfCancellationRequested();
cancellationToken.ThrowIfCancellationRequested();
diagnostics.Add(diagnostic);
}
progressTracker.ItemCompleted();
}, fixAllContext.CancellationToken);
}, cancellationToken);
}
await Task.WhenAll(tasks).ConfigureAwait(false);
......@@ -116,7 +118,8 @@ public abstract class DiagnosticProvider
return ImmutableDictionary<Document, ImmutableArray<Diagnostic>>.Empty;
}
return await GetDocumentDiagnosticsToFixAsync(allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false);
return await GetDocumentDiagnosticsToFixAsync(
allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false);
}
}
......@@ -132,7 +135,7 @@ public abstract class DiagnosticProvider
{
cancellationToken.ThrowIfCancellationRequested();
var document = documentAndDiagnostics.Key;
if (!document.IsGeneratedCode())
if (!document.IsGeneratedCode(cancellationToken))
{
var diagnosticsForDocument = documentAndDiagnostics.ToImmutableArray();
builder.Add(document, diagnosticsForDocument);
......
......@@ -53,9 +53,7 @@ protected static TextSpan GetSpan(SyntaxNode node)
}
public bool CanAddTo(SyntaxNode destination, Solution solution, CancellationToken cancellationToken)
{
return CanAddTo(destination, solution, cancellationToken, out var availableIndices);
}
=> CanAddTo(destination, solution, cancellationToken, out var availableIndices);
private bool CanAddTo(SyntaxNode destination, Solution solution, CancellationToken cancellationToken,
out IList<bool> availableIndices, bool checkGeneratedCode = false)
......@@ -75,7 +73,7 @@ public bool CanAddTo(SyntaxNode destination, Solution solution, CancellationToke
}
// check for generated files if needed.
if (checkGeneratedCode && document.IsGeneratedCode())
if (checkGeneratedCode && document.IsGeneratedCode(cancellationToken))
{
return false;
}
......@@ -202,4 +200,4 @@ private static async Task<SyntaxNode> SelectFirstOrDefaultAsync(IEnumerable<Synt
return null;
}
}
}
}
\ 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.Composition;
using System.IO;
using Microsoft.CodeAnalysis.Host;
using System.Threading;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.GeneratedCodeRecognition
{
[ExportWorkspaceServiceFactory(typeof(IGeneratedCodeRecognitionService), ServiceLayer.Default), Shared]
internal class GeneratedCodeRecognitionServiceFactory : IWorkspaceServiceFactory
[ExportWorkspaceService(typeof(IGeneratedCodeRecognitionService)), Shared]
internal class GeneratedCodeRecognitionService : IGeneratedCodeRecognitionService
{
private static readonly IGeneratedCodeRecognitionService s_singleton = new GeneratedCodeRecognitionService();
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
public bool IsGeneratedCode(Document document, CancellationToken cancellationToken)
{
return s_singleton;
}
private class GeneratedCodeRecognitionService : IGeneratedCodeRecognitionService
{
public bool IsGeneratedCode(Document document)
{
return IsFileNameForGeneratedCode(document.Name);
}
private static bool IsFileNameForGeneratedCode(string fileName)
{
if (fileName.StartsWith("TemporaryGeneratedFile_", StringComparison.OrdinalIgnoreCase))
{
return true;
}
string extension = Path.GetExtension(fileName);
if (extension != string.Empty)
{
fileName = Path.GetFileNameWithoutExtension(fileName);
if (fileName.EndsWith(".designer", StringComparison.OrdinalIgnoreCase) ||
fileName.EndsWith(".generated", StringComparison.OrdinalIgnoreCase) ||
fileName.EndsWith(".g", StringComparison.OrdinalIgnoreCase) ||
fileName.EndsWith(".g.i", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
var syntaxTree = document.GetSyntaxTreeSynchronously(cancellationToken);
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
return GeneratedCodeUtilities.IsGeneratedCode(
syntaxTree, t => syntaxFacts.IsRegularComment(t) || syntaxFacts.IsDocumentationComment(t), cancellationToken);
}
}
}
}
\ 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.Threading;
using Microsoft.CodeAnalysis.Host;
namespace Microsoft.CodeAnalysis.GeneratedCodeRecognition
{
internal interface IGeneratedCodeRecognitionService : IWorkspaceService
{
bool IsGeneratedCode(Document document);
bool IsGeneratedCode(Document document, CancellationToken cancellationToken);
}
}
}
\ No newline at end of file
......@@ -36,11 +36,15 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsTypeNamedVarInVariableOrFieldDeclaration(SyntaxToken token, SyntaxNode parent);
bool IsTypeNamedDynamic(SyntaxToken token, SyntaxNode parent);
bool IsDocumentationComment(SyntaxNode node);
bool IsUsingOrExternOrImport(SyntaxNode node);
bool IsGlobalAttribute(SyntaxNode node);
bool IsDeclaration(SyntaxNode node);
bool IsRegularComment(SyntaxTrivia trivia);
bool IsDocumentationComment(SyntaxTrivia trivia);
bool IsDocumentationComment(SyntaxNode node);
bool IsNumericLiteralExpression(SyntaxNode node);
bool IsNullLiteralExpression(SyntaxNode node);
......
......@@ -190,11 +190,11 @@ public static async Task<SemanticModel> GetPartialSemanticModelAsync(this Docume
}
}
public static bool IsGeneratedCode(this Document document)
public static bool IsGeneratedCode(this Document document, CancellationToken cancellationToken)
{
var solution = document.Project.Solution;
var generatedCodeRecognitionService = solution.Workspace.Services.GetService<IGeneratedCodeRecognitionService>();
return generatedCodeRecognitionService != null && generatedCodeRecognitionService.IsGeneratedCode(document);
return generatedCodeRecognitionService?.IsGeneratedCode(document, cancellationToken) == true;
}
}
}
\ No newline at end of file
......@@ -19,5 +19,8 @@ public static bool IsWord(this ISyntaxFactsService syntaxFacts, SyntaxToken toke
{
return syntaxFacts.IsSimpleMemberAccessExpression(node) || syntaxFacts.IsPointerMemberAccessExpression(node);
}
public static bool IsRegularOrDocumentationComment(this ISyntaxFactsService syntaxFacts, SyntaxTrivia trivia)
=> syntaxFacts.IsRegularComment(trivia) || syntaxFacts.IsDocumentationComment(trivia);
}
}
}
\ No newline at end of file
......@@ -90,6 +90,9 @@
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\FileNameUtilities.cs">
<Link>InternalUtilities\PathUtilities.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\GeneratedCodeUtilities.cs">
<Link>InternalUtilities\GeneratedCodeUtilities.cs</Link>
</Compile>
<Compile Include="..\..\..\Compilers\Core\Portable\InternalUtilities\Hash.cs">
<Link>InternalUtilities\Hash.cs</Link>
</Compile>
......
// 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.Threading;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Xunit;
......@@ -53,11 +54,11 @@ private static void TestFileNames(bool assertGenerated, params string[] fileName
var document = project.AddDocument(fileName, "");
if (assertGenerated)
{
Assert.True(document.IsGeneratedCode(), string.Format("Expected file '{0}' to be interpreted as generated code", fileName));
Assert.True(document.IsGeneratedCode(CancellationToken.None), string.Format("Expected file '{0}' to be interpreted as generated code", fileName));
}
else
{
Assert.False(document.IsGeneratedCode(), string.Format("Did not expect file '{0}' to be interpreted as generated code", fileName));
Assert.False(document.IsGeneratedCode(CancellationToken.None), string.Format("Did not expect file '{0}' to be interpreted as generated code", fileName));
}
}
}
......
......@@ -1632,5 +1632,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Function IsEndOfLineTrivia(trivia As SyntaxTrivia) As Boolean Implements ISyntaxFactsService.IsEndOfLineTrivia
Return trivia.IsEndOfLine()
End Function
Public Function IsRegularComment(trivia As SyntaxTrivia) As Boolean Implements ISyntaxFactsService.IsRegularComment
Return trivia.Kind = SyntaxKind.CommentTrivia
End Function
Public Function IsDocumentationComment(trivia As SyntaxTrivia) As Boolean Implements ISyntaxFactsService.IsDocumentationComment
Return trivia.Kind = SyntaxKind.DocumentationCommentTrivia
End Function
End Class
End Namespace
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册