/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/Core/Impl/CodeModel/RootCodeModel.cs
190 строк
8 KB
Cyrus Najmabadi
Use file scoped namespaces. (#77854)
27 мар 2025, 09:55
Не верифицирован
27 мар 2025, 09:55
98d41b8
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.IO; using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.ExternalElements; using Microsoft.VisualStudio.LanguageServices.Implementation.Interop; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; using Roslyn.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel; [ComVisible(true)] [ComDefaultInterface(typeof(EnvDTE.CodeModel))] public sealed class RootCodeModel : AbstractCodeModelObject, ICodeElementContainer<AbstractExternalCodeElement>, EnvDTE.CodeModel, EnvDTE80.CodeModel2 { internal static EnvDTE.CodeModel Create(CodeModelState state, EnvDTE.Project parent, ProjectId projectId) { var rootCodeModel = new RootCodeModel(state, parent, projectId); return (EnvDTE.CodeModel)ComAggregate.CreateAggregatedObject(rootCodeModel); } private readonly ParentHandle<EnvDTE.Project> _parentHandle; private readonly ProjectId _projectId; private RootCodeModel(CodeModelState state, EnvDTE.Project parent, ProjectId projectId) : base(state) { _parentHandle = new ParentHandle<EnvDTE.Project>(parent); _projectId = projectId; } private Project GetProject() => Workspace.CurrentSolution.GetProject(_projectId); private Task<Compilation> GetCompilationAsync() => GetProject().GetCompilationAsync(); private ComHandle<EnvDTE80.FileCodeModel2, FileCodeModel> GetFileCodeModel(object location) { if (location is string locationString) { var vsProject = _parentHandle.Value; var vsProjectItems = vsProject.ProjectItems; if (vsProjectItems == null) { throw Exceptions.ThrowEFail(); } var project = GetProject(); var projectDirectory = Path.GetDirectoryName(project.FilePath); var absoluteFilePath = Path.GetFullPath(Path.Combine(projectDirectory, locationString)); var foundFile = false; foreach (var documentId in project.DocumentIds) { var document = project.GetDocument(documentId); if (document.FilePath != null && string.Equals(absoluteFilePath, document.FilePath, StringComparison.OrdinalIgnoreCase)) { foundFile = true; break; } } if (!foundFile) { // File doesn't belong to the project, prepare & add it to project using (FileUtilities.CreateFileStreamChecked(File.Create, absoluteFilePath)) { // Note: We just want to create an empty file here, so we immediately close it. } vsProjectItems.AddFromFile(absoluteFilePath); } return this.State.ProjectCodeModelFactory.GetProjectCodeModel(_projectId).GetOrCreateFileCodeModel(absoluteFilePath); } throw Exceptions.ThrowEInvalidArg(); } public EnvDTE.Project Parent { get { return _parentHandle.Value; } } public bool IsCaseSensitive { get { return SyntaxFactsService.IsCaseSensitive; } } public EnvDTE.CodeAttribute AddAttribute(string name, object location, string value, object position) => GetFileCodeModel(location).Object.AddAttribute(name, value, position); public EnvDTE.CodeClass AddClass(string name, object location, object position, object bases, object implementedInterfaces, EnvDTE.vsCMAccess access) => GetFileCodeModel(location).Object.AddClass(name, position, bases, implementedInterfaces, access); public EnvDTE.CodeDelegate AddDelegate(string name, object location, object type, object position, EnvDTE.vsCMAccess access) => GetFileCodeModel(location).Object.AddDelegate(name, type, position, access); public EnvDTE.CodeEnum AddEnum(string name, object location, object position, object bases, EnvDTE.vsCMAccess access) => GetFileCodeModel(location).Object.AddEnum(name, position, bases, access); public EnvDTE.CodeFunction AddFunction(string name, object location, EnvDTE.vsCMFunction kind, object type, object position, EnvDTE.vsCMAccess access) => GetFileCodeModel(location).Object.AddFunction(name, kind, type, position, access); public EnvDTE.CodeInterface AddInterface(string name, object location, object position, object bases, EnvDTE.vsCMAccess access) => GetFileCodeModel(location).Object.AddInterface(name, position, bases, access); public EnvDTE.CodeNamespace AddNamespace(string name, object location, object position) => GetFileCodeModel(location).Object.AddNamespace(name, position); public EnvDTE.CodeStruct AddStruct(string name, object location, object position, object bases, object implementedInterfaces, EnvDTE.vsCMAccess access) => GetFileCodeModel(location).Object.AddStruct(name, position, bases, implementedInterfaces, access); public EnvDTE.CodeVariable AddVariable(string name, object location, object type, object position, EnvDTE.vsCMAccess access) => GetFileCodeModel(location).Object.AddVariable(name, type, position, access); EnvDTE.CodeElements ICodeElementContainer<AbstractExternalCodeElement>.GetCollection() => CodeElements; public EnvDTE.CodeElements CodeElements => this.State.ThreadingContext.JoinableTaskFactory.Run(async () => { var compilation = await GetCompilationAsync().ConfigureAwait(true); // Need to ensure we're on the UI thread to make the ExternalCodeNamespace. It creates UI thread bound // com aggregates. await this.State.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); var rootNamespace = ExternalCodeNamespace.Create(this.State, _projectId, compilation.GlobalNamespace); return rootNamespace.Members; }); public EnvDTE.CodeType CodeTypeFromFullName(string name) => this.State.ThreadingContext.JoinableTaskFactory.Run(async () => { var compilation = await GetCompilationAsync().ConfigureAwait(true); var typeSymbol = CodeModelService.GetTypeSymbolFromFullName(name, compilation); if (typeSymbol == null || typeSymbol.TypeKind is TypeKind.Error or TypeKind.Unknown) { return null; } // Need to ensure we're on the UI thread to make the call to CreateCodeType. It creates UI thread // bound com aggregates. await this.State.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); return (EnvDTE.CodeType)CodeModelService.CreateCodeType(this.State, _projectId, typeSymbol); }); public EnvDTE.CodeTypeRef CreateCodeTypeRef(object type) => CodeModelService.CreateCodeTypeRef(this.State, _projectId, type); public bool IsValidID(string name) => SyntaxFactsService.IsValidIdentifier(name); public void Remove(object element) => throw Exceptions.ThrowENotImpl(); public string DotNetNameFromLanguageSpecific(string languageName) => this.State.ThreadingContext.JoinableTaskFactory.Run(async () => { var compilation = await GetCompilationAsync().ConfigureAwait(true); var typeSymbol = CodeModelService.GetTypeSymbolFromFullName(languageName, compilation); if (typeSymbol == null) throw Exceptions.ThrowEInvalidArg(); return MetadataNameHelpers.GetMetadataName(typeSymbol); }); public EnvDTE.CodeElement ElementFromID(string id) => throw Exceptions.ThrowENotImpl(); public string LanguageSpecificNameFromDotNet(string dotNetName) { // VB implemented this but C# never did. Does it matter? throw Exceptions.ThrowENotImpl(); } public void Synchronize() => throw Exceptions.ThrowENotImpl(); }