提交 b0799619 编写于 作者: H HeeJae Chang 提交者: Sam Harwell

Support document-specific services with IDocumentService

上级 0bcb70c3
...@@ -32,6 +32,7 @@ public class TestHostDocument ...@@ -32,6 +32,7 @@ public class TestHostDocument
private readonly SourceCodeKind _sourceCodeKind; private readonly SourceCodeKind _sourceCodeKind;
private readonly string _filePath; private readonly string _filePath;
private readonly IReadOnlyList<string> _folders; private readonly IReadOnlyList<string> _folders;
private readonly IDocumentServiceProvider _documentServiceProvider;
public DocumentId Id public DocumentId Id
{ {
...@@ -101,7 +102,8 @@ public bool IsGenerated ...@@ -101,7 +102,8 @@ public bool IsGenerated
IDictionary<string, ImmutableArray<TextSpan>> spans, IDictionary<string, ImmutableArray<TextSpan>> spans,
SourceCodeKind sourceCodeKind = SourceCodeKind.Regular, SourceCodeKind sourceCodeKind = SourceCodeKind.Regular,
IReadOnlyList<string> folders = null, IReadOnlyList<string> folders = null,
bool isLinkFile = false) bool isLinkFile = false,
IDocumentServiceProvider documentServiceProvider = null)
{ {
Contract.ThrowIfNull(textBuffer); Contract.ThrowIfNull(textBuffer);
Contract.ThrowIfNull(filePath); Contract.ThrowIfNull(filePath);
...@@ -117,6 +119,7 @@ public bool IsGenerated ...@@ -117,6 +119,7 @@ public bool IsGenerated
this.CursorPosition = cursorPosition; this.CursorPosition = cursorPosition;
_sourceCodeKind = sourceCodeKind; _sourceCodeKind = sourceCodeKind;
this.IsLinkFile = isLinkFile; this.IsLinkFile = isLinkFile;
_documentServiceProvider = documentServiceProvider;
this.SelectedSpans = new List<TextSpan>(); this.SelectedSpans = new List<TextSpan>();
if (spans.ContainsKey(string.Empty)) if (spans.ContainsKey(string.Empty))
...@@ -281,7 +284,7 @@ internal void CloseTextView() ...@@ -281,7 +284,7 @@ internal void CloseTextView()
public DocumentInfo ToDocumentInfo() public DocumentInfo ToDocumentInfo()
{ {
return DocumentInfo.Create(this.Id, this.Name, this.Folders, this.SourceCodeKind, loader: this.Loader, filePath: this.FilePath, isGenerated: this.IsGenerated); return DocumentInfo.Create(this.Id, this.Name, this.Folders, this.SourceCodeKind, loader: this.Loader, filePath: this.FilePath, isGenerated: this.IsGenerated, _documentServiceProvider);
} }
} }
} }
...@@ -71,12 +71,13 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true, ...@@ -71,12 +71,13 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true,
return Create(workspaceElement, completed, openDocuments, exportProvider, workspaceKind); return Create(workspaceElement, completed, openDocuments, exportProvider, workspaceKind);
} }
public static TestWorkspace Create( internal static TestWorkspace Create(
XElement workspaceElement, XElement workspaceElement,
bool completed = true, bool completed = true,
bool openDocuments = true, bool openDocuments = true,
ExportProvider exportProvider = null, ExportProvider exportProvider = null,
string workspaceKind = null) string workspaceKind = null,
IDocumentServiceProvider documentServiceProvider = null)
{ {
if (workspaceElement.Name != WorkspaceElementName) if (workspaceElement.Name != WorkspaceElementName)
{ {
...@@ -103,6 +104,7 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true, ...@@ -103,6 +104,7 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true,
workspace, workspace,
documentElementToFilePath, documentElementToFilePath,
filePathToTextBufferMap, filePathToTextBufferMap,
documentServiceProvider,
ref projectIdentifier, ref projectIdentifier,
ref documentIdentifier); ref documentIdentifier);
Assert.False(projectNameToTestHostProject.ContainsKey(project.Name), $"The workspace XML already contains a project with name {project.Name}"); Assert.False(projectNameToTestHostProject.ContainsKey(project.Name), $"The workspace XML already contains a project with name {project.Name}");
...@@ -255,6 +257,7 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true, ...@@ -255,6 +257,7 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true,
TestWorkspace workspace, TestWorkspace workspace,
Dictionary<XElement, string> documentElementToFilePath, Dictionary<XElement, string> documentElementToFilePath,
Dictionary<string, ITextBuffer> filePathToTextBufferMap, Dictionary<string, ITextBuffer> filePathToTextBufferMap,
IDocumentServiceProvider documentServiceProvider,
ref int projectId, ref int projectId,
ref int documentId) ref int documentId)
{ {
...@@ -303,6 +306,7 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true, ...@@ -303,6 +306,7 @@ public static TestWorkspace Create(string xmlDefinition, bool completed = true,
exportProvider, exportProvider,
languageServices, languageServices,
filePathToTextBufferMap, filePathToTextBufferMap,
documentServiceProvider,
ref documentId); ref documentId);
documents.Add(document); documents.Add(document);
...@@ -584,6 +588,7 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa ...@@ -584,6 +588,7 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa
ExportProvider exportProvider, ExportProvider exportProvider,
HostLanguageServices languageServiceProvider, HostLanguageServices languageServiceProvider,
Dictionary<string, ITextBuffer> filePathToTextBufferMap, Dictionary<string, ITextBuffer> filePathToTextBufferMap,
IDocumentServiceProvider documentServiceProvider,
ref int documentId) ref int documentId)
{ {
string markupCode; string markupCode;
...@@ -674,7 +679,8 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa ...@@ -674,7 +679,8 @@ private static CompilationOptions CreateCompilationOptions(TestWorkspace workspa
filePathToTextBufferMap.Add(filePath, textBuffer); filePathToTextBufferMap.Add(filePath, textBuffer);
} }
return new TestHostDocument(exportProvider, languageServiceProvider, textBuffer, filePath, cursorPosition, spans, codeKind, folders, isLinkFile); return new TestHostDocument(
exportProvider, languageServiceProvider, textBuffer, filePath, cursorPosition, spans, codeKind, folders, isLinkFile, documentServiceProvider);
} }
private static string GetFilePath( private static string GetFilePath(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList; using Microsoft.VisualStudio.LanguageServices.Implementation.TaskList;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -431,9 +432,14 @@ public void AddSourceFile(string fullPath, SourceCodeKind sourceCodeKind = Sourc ...@@ -431,9 +432,14 @@ public void AddSourceFile(string fullPath, SourceCodeKind sourceCodeKind = Sourc
_sourceFiles.AddFile(fullPath, sourceCodeKind, folders); _sourceFiles.AddFile(fullPath, sourceCodeKind, folders);
} }
public DocumentId AddSourceTextContainer(SourceTextContainer textContainer, string fullPath, SourceCodeKind sourceCodeKind = SourceCodeKind.Regular, ImmutableArray<string> folders = default) public DocumentId AddSourceTextContainer(
SourceTextContainer textContainer,
string fullPath,
SourceCodeKind sourceCodeKind = SourceCodeKind.Regular,
ImmutableArray<string> folders = default,
IDocumentServiceProvider documentServiceProvider = null)
{ {
return _sourceFiles.AddTextContainer(textContainer, fullPath, sourceCodeKind, folders); return _sourceFiles.AddTextContainer(textContainer, fullPath, sourceCodeKind, folders, documentServiceProvider);
} }
public bool ContainsSourceFile(string fullPath) public bool ContainsSourceFile(string fullPath)
...@@ -902,7 +908,7 @@ public DocumentId AddFile(string fullPath, SourceCodeKind sourceCodeKind, Immuta ...@@ -902,7 +908,7 @@ public DocumentId AddFile(string fullPath, SourceCodeKind sourceCodeKind, Immuta
return documentId; return documentId;
} }
public DocumentId AddTextContainer(SourceTextContainer textContainer, string fullPath, SourceCodeKind sourceCodeKind, ImmutableArray<string> folders) public DocumentId AddTextContainer(SourceTextContainer textContainer, string fullPath, SourceCodeKind sourceCodeKind, ImmutableArray<string> folders, IDocumentServiceProvider documentServiceProvider)
{ {
if (textContainer == null) if (textContainer == null)
{ {
...@@ -917,7 +923,9 @@ public DocumentId AddTextContainer(SourceTextContainer textContainer, string ful ...@@ -917,7 +923,9 @@ public DocumentId AddTextContainer(SourceTextContainer textContainer, string ful
folders: folders.IsDefault ? null : (IEnumerable<string>)folders, folders: folders.IsDefault ? null : (IEnumerable<string>)folders,
sourceCodeKind: sourceCodeKind, sourceCodeKind: sourceCodeKind,
loader: textLoader, loader: textLoader,
filePath: fullPath); filePath: fullPath,
isGenerated: false,
documentServiceProvider: documentServiceProvider);
lock (_project._gate) lock (_project._gate)
{ {
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.Host
{
/// <summary>
/// Empty interface just to mark document services.
/// </summary>
internal interface IDocumentService
{
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.Host
{
internal interface IDocumentServiceProvider
{
/// <summary>
/// Gets a document specific service provided by the host identified by the service type.
/// If the host does not provide the service, this method returns null.
/// </summary>
TService GetService<TService>() where TService : class, IDocumentService;
}
}
// 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.Host;
namespace Microsoft.CodeAnalysis
{
/// <summary>
/// <see cref="IDocumentServiceProvider"/> for regular C#/VB files.
/// </summary>
internal sealed class DefaultTextDocumentServiceProvider : IDocumentServiceProvider
{
public static readonly DefaultTextDocumentServiceProvider Instance = new DefaultTextDocumentServiceProvider();
private DefaultTextDocumentServiceProvider() { }
public TService GetService<TService>() where TService : class, IDocumentService
{
return default;
}
}
}
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Serialization; using Microsoft.CodeAnalysis.Serialization;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -53,13 +54,19 @@ public sealed class DocumentInfo ...@@ -53,13 +54,19 @@ public sealed class DocumentInfo
/// </summary> /// </summary>
public TextLoader TextLoader { get; } public TextLoader TextLoader { get; }
/// <summary>
/// A <see cref="IDocumentServiceProvider"/> associated with this document
/// </summary>
internal IDocumentServiceProvider DocumentServiceProvider { get; }
/// <summary> /// <summary>
/// Create a new instance of a <see cref="DocumentInfo"/>. /// Create a new instance of a <see cref="DocumentInfo"/>.
/// </summary> /// </summary>
internal DocumentInfo(DocumentAttributes attributes, TextLoader loader) internal DocumentInfo(DocumentAttributes attributes, TextLoader loader, IDocumentServiceProvider documentServiceProvider)
{ {
Attributes = attributes; Attributes = attributes;
TextLoader = loader; TextLoader = loader;
DocumentServiceProvider = documentServiceProvider;
} }
public static DocumentInfo Create( public static DocumentInfo Create(
...@@ -71,22 +78,39 @@ internal DocumentInfo(DocumentAttributes attributes, TextLoader loader) ...@@ -71,22 +78,39 @@ internal DocumentInfo(DocumentAttributes attributes, TextLoader loader)
string filePath = null, string filePath = null,
bool isGenerated = false) bool isGenerated = false)
{ {
return new DocumentInfo(new DocumentAttributes(id, name, folders, sourceCodeKind, filePath, isGenerated), loader); return Create(id, name, folders, sourceCodeKind, loader, filePath, isGenerated, documentServiceProvider: null);
}
internal static DocumentInfo Create(
DocumentId id,
string name,
IEnumerable<string> folders,
SourceCodeKind sourceCodeKind,
TextLoader loader,
string filePath,
bool isGenerated,
IDocumentServiceProvider documentServiceProvider)
{
return new DocumentInfo(new DocumentAttributes(id, name, folders, sourceCodeKind, filePath, isGenerated), loader, documentServiceProvider);
} }
private DocumentInfo With( private DocumentInfo With(
DocumentAttributes attributes = null, DocumentAttributes attributes = null,
Optional<TextLoader> loader = default) Optional<TextLoader> loader = default,
Optional<IDocumentServiceProvider> documentServiceProvider = default)
{ {
var newAttributes = attributes ?? Attributes; var newAttributes = attributes ?? Attributes;
var newLoader = loader.HasValue ? loader.Value : TextLoader; var newLoader = loader.HasValue ? loader.Value : TextLoader;
var newDocumentServiceProvider = documentServiceProvider.HasValue ? documentServiceProvider.Value : DocumentServiceProvider;
if (newAttributes == Attributes && newLoader == TextLoader) if (newAttributes == Attributes &&
newLoader == TextLoader &&
newDocumentServiceProvider == DocumentServiceProvider)
{ {
return this; return this;
} }
return new DocumentInfo(newAttributes, newLoader); return new DocumentInfo(newAttributes, newLoader, newDocumentServiceProvider);
} }
public DocumentInfo WithId(DocumentId id) public DocumentInfo WithId(DocumentId id)
......
...@@ -28,13 +28,14 @@ internal partial class DocumentState : TextDocumentState ...@@ -28,13 +28,14 @@ internal partial class DocumentState : TextDocumentState
private DocumentState( private DocumentState(
HostLanguageServices languageServices, HostLanguageServices languageServices,
SolutionServices solutionServices, SolutionServices solutionServices,
IDocumentServiceProvider documentServiceProvider,
DocumentInfo.DocumentAttributes attributes, DocumentInfo.DocumentAttributes attributes,
ParseOptions options, ParseOptions options,
SourceText sourceTextOpt, SourceText sourceTextOpt,
ValueSource<TextAndVersion> textSource, ValueSource<TextAndVersion> textSource,
ValueSource<TreeAndVersion> treeSource, ValueSource<TreeAndVersion> treeSource,
ValueSource<DocumentStateChecksums> lazyChecksums) ValueSource<DocumentStateChecksums> lazyChecksums)
: base(solutionServices, attributes, sourceTextOpt, textSource, lazyChecksums) : base(solutionServices, documentServiceProvider, attributes, sourceTextOpt, textSource, lazyChecksums)
{ {
_languageServices = languageServices; _languageServices = languageServices;
_options = options; _options = options;
...@@ -75,6 +76,7 @@ internal bool SupportsSyntaxTree ...@@ -75,6 +76,7 @@ internal bool SupportsSyntaxTree
return new DocumentState( return new DocumentState(
languageServices: language, languageServices: language,
documentServiceProvider: info.DocumentServiceProvider,
solutionServices: services, solutionServices: services,
attributes: info.Attributes, attributes: info.Attributes,
options: options, options: options,
...@@ -332,6 +334,7 @@ private DocumentState SetParseOptions(ParseOptions options) ...@@ -332,6 +334,7 @@ private DocumentState SetParseOptions(ParseOptions options)
return new DocumentState( return new DocumentState(
this.LanguageServices, this.LanguageServices,
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes.With(sourceCodeKind: options.Kind), this.Attributes.With(sourceCodeKind: options.Kind),
options, options,
this.sourceTextOpt, this.sourceTextOpt,
...@@ -355,6 +358,7 @@ public DocumentState UpdateName(string name) ...@@ -355,6 +358,7 @@ public DocumentState UpdateName(string name)
return new DocumentState( return new DocumentState(
_languageServices, _languageServices,
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes.With(name: name), this.Attributes.With(name: name),
_options, _options,
this.sourceTextOpt, this.sourceTextOpt,
...@@ -368,6 +372,7 @@ public DocumentState UpdateFolders(IList<string> folders) ...@@ -368,6 +372,7 @@ public DocumentState UpdateFolders(IList<string> folders)
return new DocumentState( return new DocumentState(
_languageServices, _languageServices,
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes.With(folders: folders), this.Attributes.With(folders: folders),
_options, _options,
this.sourceTextOpt, this.sourceTextOpt,
...@@ -381,6 +386,7 @@ public DocumentState UpdateFilePath(string filePath) ...@@ -381,6 +386,7 @@ public DocumentState UpdateFilePath(string filePath)
return new DocumentState( return new DocumentState(
_languageServices, _languageServices,
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes.With(filePath: filePath), this.Attributes.With(filePath: filePath),
_options, _options,
this.sourceTextOpt, this.sourceTextOpt,
...@@ -428,6 +434,7 @@ public new DocumentState UpdateText(TextAndVersion newTextAndVersion, Preservati ...@@ -428,6 +434,7 @@ public new DocumentState UpdateText(TextAndVersion newTextAndVersion, Preservati
return new DocumentState( return new DocumentState(
this.LanguageServices, this.LanguageServices,
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes, this.Attributes,
_options, _options,
sourceTextOpt: null, sourceTextOpt: null,
...@@ -469,6 +476,7 @@ internal DocumentState UpdateText(TextLoader loader, SourceText textOpt, Preserv ...@@ -469,6 +476,7 @@ internal DocumentState UpdateText(TextLoader loader, SourceText textOpt, Preserv
return new DocumentState( return new DocumentState(
this.LanguageServices, this.LanguageServices,
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes, this.Attributes,
_options, _options,
sourceTextOpt: textOpt, sourceTextOpt: textOpt,
...@@ -511,6 +519,7 @@ internal DocumentState UpdateTree(SyntaxNode newRoot, PreservationMode mode) ...@@ -511,6 +519,7 @@ internal DocumentState UpdateTree(SyntaxNode newRoot, PreservationMode mode)
return new DocumentState( return new DocumentState(
this.LanguageServices, this.LanguageServices,
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes, this.Attributes,
_options, _options,
sourceTextOpt: null, sourceTextOpt: null,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -51,6 +52,11 @@ internal TextDocument(Project project, TextDocumentState state) ...@@ -51,6 +52,11 @@ internal TextDocument(Project project, TextDocumentState state)
/// </summary> /// </summary>
public IReadOnlyList<string> Folders => State.Folders; public IReadOnlyList<string> Folders => State.Folders;
/// <summary>
/// A <see cref="IDocumentServiceProvider"/> associated with this document
/// </summary>
internal IDocumentServiceProvider Services => State.Services;
/// <summary> /// <summary>
/// Get the current text for the document if it is already loaded and available. /// Get the current text for the document if it is already loaded and available.
/// </summary> /// </summary>
......
...@@ -39,6 +39,7 @@ internal partial class TextDocumentState ...@@ -39,6 +39,7 @@ internal partial class TextDocumentState
protected TextDocumentState( protected TextDocumentState(
SolutionServices solutionServices, SolutionServices solutionServices,
IDocumentServiceProvider documentServiceProvider,
DocumentInfo.DocumentAttributes attributes, DocumentInfo.DocumentAttributes attributes,
SourceText sourceTextOpt, SourceText sourceTextOpt,
ValueSource<TextAndVersion> textAndVersionSource, ValueSource<TextAndVersion> textAndVersionSource,
...@@ -49,6 +50,7 @@ internal partial class TextDocumentState ...@@ -49,6 +50,7 @@ internal partial class TextDocumentState
this.textAndVersionSource = textAndVersionSource; this.textAndVersionSource = textAndVersionSource;
Attributes = attributes; Attributes = attributes;
Services = documentServiceProvider ?? DefaultTextDocumentServiceProvider.Instance;
// for now, let it re-calculate if anything changed. // for now, let it re-calculate if anything changed.
// TODO: optimize this so that we only re-calcuate checksums that are actually changed // TODO: optimize this so that we only re-calcuate checksums that are actually changed
...@@ -57,6 +59,11 @@ internal partial class TextDocumentState ...@@ -57,6 +59,11 @@ internal partial class TextDocumentState
public DocumentInfo.DocumentAttributes Attributes { get; } public DocumentInfo.DocumentAttributes Attributes { get; }
/// <summary>
/// A <see cref="IDocumentServiceProvider"/> associated with this document
/// </summary>
public IDocumentServiceProvider Services { get; }
public DocumentId Id public DocumentId Id
{ {
get { return Attributes.Id; } get { return Attributes.Id; }
...@@ -85,6 +92,7 @@ public static TextDocumentState Create(DocumentInfo info, SolutionServices servi ...@@ -85,6 +92,7 @@ public static TextDocumentState Create(DocumentInfo info, SolutionServices servi
return new TextDocumentState( return new TextDocumentState(
solutionServices: services, solutionServices: services,
documentServiceProvider: info.DocumentServiceProvider,
attributes: info.Attributes, attributes: info.Attributes,
sourceTextOpt: null, sourceTextOpt: null,
textAndVersionSource: textSource, textAndVersionSource: textSource,
...@@ -320,6 +328,7 @@ public TextDocumentState UpdateText(TextAndVersion newTextAndVersion, Preservati ...@@ -320,6 +328,7 @@ public TextDocumentState UpdateText(TextAndVersion newTextAndVersion, Preservati
return new TextDocumentState( return new TextDocumentState(
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes, this.Attributes,
sourceTextOpt: null, sourceTextOpt: null,
textAndVersionSource: newTextSource, textAndVersionSource: newTextSource,
...@@ -354,6 +363,7 @@ public TextDocumentState UpdateText(TextLoader loader, PreservationMode mode) ...@@ -354,6 +363,7 @@ public TextDocumentState UpdateText(TextLoader loader, PreservationMode mode)
return new TextDocumentState( return new TextDocumentState(
this.solutionServices, this.solutionServices,
this.Services,
this.Attributes, this.Attributes,
sourceTextOpt: null, sourceTextOpt: null,
textAndVersionSource: newTextSource, textAndVersionSource: newTextSource,
......
...@@ -1384,7 +1384,9 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges) ...@@ -1384,7 +1384,9 @@ protected virtual void ApplyProjectChanges(ProjectChanges projectChanges)
if (newDoc.HasInfoChanged(oldDoc)) if (newDoc.HasInfoChanged(oldDoc))
{ {
// ApplyDocumentInfoChanged ignores the loader information, so we can pass null for it // ApplyDocumentInfoChanged ignores the loader information, so we can pass null for it
ApplyDocumentInfoChanged(documentId, new DocumentInfo(newDoc.State.Attributes, loader: null)); ApplyDocumentInfoChanged(
documentId,
new DocumentInfo(newDoc.State.Attributes, loader: null, documentServiceProvider: newDoc.State.Services));
} }
// update text if changed // update text if changed
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册