Skip to content

Commit

Permalink
Merge pull request #32451 from dotnet/merges/dev16.0-preview2-to-master
Browse files Browse the repository at this point in the history
Merge dev16.0-preview2 to master
  • Loading branch information
dotnet-automerge-bot authored Jan 15, 2019
2 parents b16398f + 9bd71d0 commit 33e2546
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 300 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3435,7 +3435,7 @@ static void Main()
}

[WorkItem(540516, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540516")]
[Fact]
[ConditionalFact(typeof(ClrOnly), Reason = "https://github.com/mono/mono/issues/12422")]
public void TestCallMethodsWithLeastCustomModifiers()
{
var text = @"using Metadata;
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Test/Emit/CodeGen/DestructorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ .maxstack 1
compVerifier.VerifyDiagnostics();
}

[ConditionalFact(typeof(DesktopOnly))]
[ConditionalFact(typeof(WindowsDesktopOnly))]
public void DestructorOverridesNonDestructor()
{
var text = @"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ protected override void ApplyDocumentTextChanged(DocumentId document, SourceText
base.ClearSolution();
}

internal void ClearOpenDocument(DocumentId documentId)
internal new void ClearOpenDocument(DocumentId documentId)
{
base.ClearOpenDocument(documentId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,32 +305,46 @@ private bool AreColorsDefaulted(Dictionary<string, ColorableItems> colorItemMap,
// happens to be the same as PlainText so an extra check isn't necessary. StructName doesn't need
// an additional check because it has a color defined in the PKGDEF. The Editor is smart enough
// to follow the BaseClassification hierarchy and render the colors appropriately.
return colorItemMap[ClassificationTypeNames.LocalName].Foreground == DarkThemeIdentifier &&
colorItemMap[ClassificationTypeNames.ParameterName].Foreground == DarkThemeIdentifier &&
colorItemMap[ClassificationTypeNames.MethodName].Foreground == DarkThemeIdentifier &&
colorItemMap[ClassificationTypeNames.ExtensionMethodName].Foreground == DarkThemeIdentifier &&
(colorItemMap[ClassificationTypeNames.OperatorOverloaded].Foreground == DarkThemePlainText ||
colorItemMap[ClassificationTypeNames.OperatorOverloaded].Foreground == DarkThemeOperator) &&
(colorItemMap[ClassificationTypeNames.ControlKeyword].Foreground == DarkThemePlainText ||
colorItemMap[ClassificationTypeNames.ControlKeyword].Foreground == DarkThemeKeyword) &&
colorItemMap[ClassificationTypeNames.StructName].Foreground == DarkThemeClass;
return IsDefaultColor(colorItemMap, ClassificationTypeNames.LocalName, DarkThemeIdentifier) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.ParameterName, DarkThemeIdentifier) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.MethodName, DarkThemeIdentifier) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.ExtensionMethodName, DarkThemeIdentifier) &&
(IsDefaultColor(colorItemMap, ClassificationTypeNames.OperatorOverloaded, DarkThemePlainText) ||
IsDefaultColor(colorItemMap, ClassificationTypeNames.OperatorOverloaded, DarkThemeOperator)) &&
(IsDefaultColor(colorItemMap, ClassificationTypeNames.ControlKeyword, DarkThemePlainText) ||
IsDefaultColor(colorItemMap, ClassificationTypeNames.ControlKeyword, DarkThemeKeyword)) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.StructName, DarkThemeClass);
}
else
{
// Light or Blue themes
// Same as above, we also check ControlKeyword for whether it is the PlainText color. OperatorOverload and
// the other Identifier types do not need an additional check because their default color is the same
// as PlainText.
return colorItemMap[ClassificationTypeNames.LocalName].Foreground == LightThemeIdentifier &&
colorItemMap[ClassificationTypeNames.ParameterName].Foreground == LightThemeIdentifier &&
colorItemMap[ClassificationTypeNames.MethodName].Foreground == LightThemeIdentifier &&
colorItemMap[ClassificationTypeNames.ExtensionMethodName].Foreground == LightThemeIdentifier &&
colorItemMap[ClassificationTypeNames.OperatorOverloaded].Foreground == LightThemeOperator &&
(colorItemMap[ClassificationTypeNames.ControlKeyword].Foreground == LightThemePlainText ||
colorItemMap[ClassificationTypeNames.ControlKeyword].Foreground == LightThemeKeyword);
return IsDefaultColor(colorItemMap, ClassificationTypeNames.LocalName, LightThemeIdentifier) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.ParameterName, LightThemeIdentifier) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.MethodName, LightThemeIdentifier) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.ExtensionMethodName, LightThemeIdentifier) &&
IsDefaultColor(colorItemMap, ClassificationTypeNames.OperatorOverloaded, LightThemeOperator) &&
(IsDefaultColor(colorItemMap, ClassificationTypeNames.ControlKeyword, LightThemePlainText) ||
IsDefaultColor(colorItemMap, ClassificationTypeNames.ControlKeyword, LightThemeKeyword));
}
}

private bool IsDefaultColor(Dictionary<string, ColorableItems> colorItemMap, string classification, uint themeColor)
{
// Without visiting the Font and Colors options dialog, the reported colors for
// classifications that do not export a color, have a color defined in the PKGDEF,
// or have a custom color set will be Black (0x00000000) for the Foreground and
// White (0x00FFFFF) for the Background. We will additionally check the foreground
// against Black and DefaultForegroundColor for completeness.

var foreground = colorItemMap[classification].Foreground;
return foreground == themeColor ||
foreground == 0 ||
foreground == DefaultForegroundColor;
}

/// <summary>
/// Determines if our enhanced colors are applied for the current theme. This is how we determine
/// if we are the color owner when trying to set default colors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,7 @@ internal sealed partial class VisualStudioRuleSetManager : IWorkspaceService
private readonly IForegroundNotificationService _foregroundNotificationService;
private readonly IAsynchronousOperationListener _listener;

/// <summary>
/// Gate that guards access to <see cref="_ruleSetFileMap"/>.
/// </summary>
private readonly object _gate = new object();

/// <summary>
/// The map of cached <see cref="RuleSetFile"/>. We use a WeakReference here because we want to strike this entry from the cache when all users are
/// disposed, but that means we ourselves don't want to be contributing to that reference count. Since consumers of this are responsible for all
/// disposing, it's safe for us to also remove entries from this map if we need to refresh -- once everybody who consumed it disposes everything,
/// the underlying file watchers will be cleaned up.
/// </summary>
private readonly Dictionary<string, ReferenceCountedDisposable<RuleSetFile>.WeakReference> _ruleSetFileMap =
new Dictionary<string, ReferenceCountedDisposable<RuleSetFile>.WeakReference>();
private readonly ReferenceCountedDisposableCache<string, RuleSetFile> _ruleSetFileMap = new ReferenceCountedDisposableCache<string, RuleSetFile>();

public VisualStudioRuleSetManager(
FileChangeWatcher fileChangeWatcher, IForegroundNotificationService foregroundNotificationService, IAsynchronousOperationListener listener)
Expand All @@ -37,36 +25,15 @@ public VisualStudioRuleSetManager(
_listener = listener;
}

public IReferenceCountedDisposable<IRuleSetFile> GetOrCreateRuleSet(string ruleSetFileFullPath)
public IReferenceCountedDisposable<ICacheEntry<string, IRuleSetFile>> GetOrCreateRuleSet(string ruleSetFileFullPath)
{
ReferenceCountedDisposable<RuleSetFile> disposable = null;

lock (_gate)
{
// If we already have one in the map to hand out, great
if (_ruleSetFileMap.TryGetValue(ruleSetFileFullPath, out var weakReference))
{
disposable = weakReference.TryAddReference();
}

if (disposable == null)
{
// We didn't easily get a disposable, so one of two things is the case:
//
// 1. We have no entry in _ruleSetFileMap at all for this.
// 2. We had an entry, but it was disposed and is no longer valid.

// In either case, we'll create a new rule set file and add it to the map.
disposable = new ReferenceCountedDisposable<RuleSetFile>(new RuleSetFile(ruleSetFileFullPath, this));
_ruleSetFileMap[ruleSetFileFullPath] = new ReferenceCountedDisposable<RuleSetFile>.WeakReference(disposable);
}
}
var cacheEntry = _ruleSetFileMap.GetOrCreate(ruleSetFileFullPath, _ => new RuleSetFile(ruleSetFileFullPath, this));

// Call InitializeFileTracking outside the lock, so we don't have requests for other files blocking behind the initialization of this one.
// RuleSetFile itself will ensure InitializeFileTracking is locked as appropriate.
disposable.Target.InitializeFileTracking(_fileChangeWatcher);
// Call InitializeFileTracking outside the lock inside ReferenceCountedDisposableCache, so we don't have requests
// for other files blocking behind the initialization of this one. RuleSetFile itself will ensure InitializeFileTracking is locked as appropriate.
cacheEntry.Target.Value.InitializeFileTracking(_fileChangeWatcher);

return disposable;
return cacheEntry;
}

private void StopTrackingRuleSetFile(RuleSetFile ruleSetFile)
Expand All @@ -82,10 +49,7 @@ private void StopTrackingRuleSetFile(RuleSetFile ruleSetFile)
// (perhaps by a file change), and we're removing a live instance. This is fine, as this doesn't affect correctness: we consider this to be a cache
// and if two callers got different copies that's fine. We *could* fetch the item out of the dictionary, check if the item is strong and then compare,
// but that seems overkill.
lock (_gate)
{
_ruleSetFileMap.Remove(ruleSetFile.FilePath);
}
_ruleSetFileMap.Evict(ruleSetFile.FilePath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class VisualStudioProjectOptionsProcessor : IDisposable
private string _commandLine = "";
private CommandLineArguments _commandLineArgumentsForCommandLine;
private string _explicitRuleSetFilePath;
private IReferenceCountedDisposable<IRuleSetFile> _ruleSetFile = null;
private IReferenceCountedDisposable<ICacheEntry<string, IRuleSetFile>> _ruleSetFile = null;

public VisualStudioProjectOptionsProcessor(VisualStudioProject project, HostWorkspaceServices workspaceServices)
{
Expand Down Expand Up @@ -94,7 +94,7 @@ private void UpdateProjectOptions_NoLock()
{
var effectiveRuleSetPath = ExplicitRuleSetFilePath ?? _commandLineArgumentsForCommandLine.RuleSetPath;

if (_ruleSetFile?.Target.FilePath != effectiveRuleSetPath)
if (_ruleSetFile?.Target.Value.FilePath != effectiveRuleSetPath)
{
// We're changing in some way. Be careful: this might mean the path is switching to or from null, so either side so far
// could be changed.
Expand Down Expand Up @@ -132,7 +132,7 @@ private void UpdateProjectOptions_NoLock()

// We've computed what the base values should be; we now give an opportunity for any host-specific settings to be computed
// before we apply them
compilationOptions = ComputeCompilationOptionsWithHostValues(compilationOptions, this._ruleSetFile?.Target);
compilationOptions = ComputeCompilationOptionsWithHostValues(compilationOptions, this._ruleSetFile?.Target.Value);
parseOptions = ComputeParseOptionsWithHostValues(parseOptions);

// For managed projects, AssemblyName has to be non-null, but the command line we get might be a partial command line
Expand Down
Loading

0 comments on commit 33e2546

Please sign in to comment.