// Copyright (c) AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.CSharp { /// /// Represents a file that was parsed and converted for the type system. /// [Serializable] public sealed class CSharpParsedFile : AbstractFreezable, IParsedFile { readonly string fileName; readonly UsingScope rootUsingScope; IList topLevelTypeDefinitions = new List(); IList assemblyAttributes = new List(); IList moduleAttributes = new List(); IList usingScopes = new List(); IList errors = new List (); protected override void FreezeInternal() { base.FreezeInternal(); rootUsingScope.Freeze(); topLevelTypeDefinitions = FreezeList(topLevelTypeDefinitions); assemblyAttributes = FreezeList(assemblyAttributes); moduleAttributes = FreezeList(moduleAttributes); usingScopes = FreezeList(usingScopes); } public CSharpParsedFile(string fileName, UsingScope rootUsingScope) { if (fileName == null) throw new ArgumentNullException("fileName"); if (rootUsingScope == null) throw new ArgumentNullException("rootUsingScope"); this.fileName = fileName; this.rootUsingScope = rootUsingScope; } public string FileName { get { return fileName; } } DateTime lastWriteTime = DateTime.UtcNow; public DateTime LastWriteTime { get { return lastWriteTime; } set { CheckBeforeMutation(); lastWriteTime = value; } } public UsingScope RootUsingScope { get { return rootUsingScope; } } public IList Errors { get { return errors; } internal set { errors = (List)value; } } public IList UsingScopes { get { return usingScopes; } } public IProjectContent ProjectContent { get { return rootUsingScope.ProjectContent; } } public IList TopLevelTypeDefinitions { get { return topLevelTypeDefinitions; } } public IList AssemblyAttributes { get { return assemblyAttributes; } } public IList ModuleAttributes { get { return moduleAttributes; } } public UsingScope GetUsingScope(AstLocation location) { foreach (UsingScope scope in usingScopes) { if (scope.Region.IsInside(location.Line, location.Column)) return scope; } return rootUsingScope; } public ITypeDefinition GetTopLevelTypeDefinition(AstLocation location) { return FindEntity(topLevelTypeDefinitions, location); } public ITypeDefinition GetInnermostTypeDefinition(AstLocation location) { ITypeDefinition parent = null; ITypeDefinition type = GetTopLevelTypeDefinition(location); while (type != null) { parent = type; type = FindEntity(parent.NestedTypes, location); } return parent; } public IMember GetMember(AstLocation location) { ITypeDefinition type = GetInnermostTypeDefinition(location); if (type == null) return null; return FindEntity(type.Methods, location) ?? FindEntity(type.Fields, location) ?? FindEntity(type.Properties, location) ?? (IMember)FindEntity(type.Events, location); } static T FindEntity(IList list, AstLocation location) where T : class, IEntity { // This could be improved using a binary search foreach (T entity in list) { if (entity.Region.IsInside(location.Line, location.Column)) return entity; } return null; } } }