// 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);
}
}
}