Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge master to dev16.1-preview1 #32468

Merged
18 commits merged into from
Jan 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
513119e
Fix up logic that is determining and setting contexts for files
jasonmalinowski Jan 9, 2019
f36378f
Extract out a reference-counted cache implementation
jasonmalinowski Jan 9, 2019
85f969b
Correctly free our IVsHierarchy subscriptions when we're done
jasonmalinowski Jan 10, 2019
29ef2e2
Make GetDocumentIdInCurrentContext non-virtual and remove the comment
jasonmalinowski Jan 10, 2019
835eb31
Don't call back into the workspace host to force change contexts
jasonmalinowski Jan 10, 2019
18bcaac
Remove hack which was trying to avoid a deadlock when projects unload
jasonmalinowski Jan 10, 2019
35f7141
Move comment to the code it actually applies to
jasonmalinowski Jan 10, 2019
045cf2d
Add comment to Workspace.OnDocumentContextUpdated
jasonmalinowski Jan 10, 2019
be1d1e5
Clean up Workspace.OnDocumentContextUpdated
jasonmalinowski Jan 10, 2019
cd5cd58
Inline a _NoLock method only being used in one place
jasonmalinowski Jan 10, 2019
5722f21
Add some documentation for Workspace.SetDocumentContext
jasonmalinowski Jan 10, 2019
dc90fbb
When responding to an IVsHierarchy change, only refresh needed files
jasonmalinowski Jan 10, 2019
68bf17c
Fix default color check used by enhanced color experiment (#32341)
JoeRobich Jan 14, 2019
878ac97
Disable a few tests on Mono
jaredpar Jan 14, 2019
225a588
Merge pull request #32436 from jaredpar/fix-mono
jaredpar Jan 15, 2019
bf4ce62
Merge pull request #32313 from jasonmalinowski/fix-context-switching-…
jasonmalinowski Jan 15, 2019
9bd71d0
Merge remote-tracking branch 'origin/master' into merges/dev16.0-prev…
JoeRobich Jan 15, 2019
33e2546
Merge pull request #32451 from dotnet/merges/dev16.0-preview2-to-master
Jan 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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