// 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 System; using System.Diagnostics; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis { /// /// A program location in source code. /// [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] public abstract class Location { internal Location() { } /// /// Location kind (None/SourceFile/MetadataFile). /// public abstract LocationKind Kind { get; } /// /// Returns true if the location represents a specific location in a source code file. /// public bool IsInSource { get { return SourceTree != null; } } /// /// Returns true if the location is in metadata. /// public bool IsInMetadata { get { return MetadataModule != null; } } /// /// The syntax tree this location is located in or null if not in a syntax tree. /// public virtual SyntaxTree SourceTree { get { return null; } } /// /// Returns the metadata module the location is associated with or null if the module is not available. /// /// /// Might return null even if returns true. The module symbol might not be available anymore, /// for example, if the location is serialized and deserialized. /// public virtual IModuleSymbol MetadataModule { get { return null; } } /// /// The location within the syntax tree that this location is associated with. /// /// /// If returns False this method returns an empty which starts at position 0. /// public virtual TextSpan SourceSpan { get { return default(TextSpan); } } /// /// Gets the location in terms of path, line and column. /// /// /// that contains path, line and column information. /// /// Returns an invalid span (see ) if the information is not available. /// /// The values are not affected by line mapping directives (#line in C# or #ExternalSource in VB). /// public virtual FileLinePositionSpan GetLineSpan() { return default(FileLinePositionSpan); } /// /// Gets the location in terms of path, line and column after applying source line mapping directives /// (`#line` in C# or `#ExternalSource` in VB). /// /// /// that contains file, line and column information, /// or an invalid span (see ) if not available. /// public virtual FileLinePositionSpan GetMappedLineSpan() { return default(FileLinePositionSpan); } // Derived classes should provide value equality semantics. public abstract override bool Equals(object obj); public abstract override int GetHashCode(); public override string ToString() { string result = Kind.ToString(); if (IsInSource) { result += "(" + this.SourceTree?.FilePath + this.SourceSpan + ")"; } else if (IsInMetadata) { if (this.MetadataModule != null) { result += "(" + this.MetadataModule.Name + ")"; } } else { var pos = GetLineSpan(); if (pos.Path != null) { // user-visible line and column counts are 1-based, but internally are 0-based. result += "(" + pos.Path + "@" + (pos.StartLinePosition.Line + 1) + ":" + (pos.StartLinePosition.Character + 1) + ")"; } } return result; } public static bool operator ==(Location left, Location right) { if (object.ReferenceEquals(left, null)) { return object.ReferenceEquals(right, null); } return left.Equals(right); } public static bool operator !=(Location left, Location right) { return !(left == right); } protected virtual string GetDebuggerDisplay() { string result = this.GetType().Name; var pos = GetLineSpan(); if (pos.Path != null) { // user-visible line and column counts are 1-based, but internally are 0-based. result += "(" + pos.Path + "@" + (pos.StartLinePosition.Line + 1) + ":" + (pos.StartLinePosition.Character + 1) + ")"; } return result; } /// /// A location of kind LocationKind.None. /// public static Location None { get { return NoLocation.Singleton; } } /// /// Creates an instance of a for a span in a . /// public static Location Create(SyntaxTree syntaxTree, TextSpan textSpan) { if (syntaxTree == null) { throw new ArgumentNullException(nameof(syntaxTree)); } return new SourceLocation(syntaxTree, textSpan); } /// /// Creates an instance of a for a span in a file. /// public static Location Create(string filePath, TextSpan textSpan, LinePositionSpan lineSpan) { if (filePath == null) { throw new ArgumentNullException(nameof(filePath)); } return new ExternalFileLocation(filePath, textSpan, lineSpan); } } }