1#region Copyright notice and license
2// Protocol Buffers - Google's data interchange format
3// Copyright 2018 Google Inc.  All rights reserved.
4// https://developers.google.com/protocol-buffers/
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10//     * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//     * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16//     * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31#endregion
32
33using System;
34using System.Collections.Generic;
35using System.Collections.ObjectModel;
36using System.Linq;
37using System.Text;
38using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
39
40namespace Google.Protobuf.Reflection
41{
42    /// <summary>
43    /// Provides additional information about the declaration of a descriptor,
44    /// such as source location and comments.
45    /// </summary>
46    public sealed class DescriptorDeclaration
47    {
48        /// <summary>
49        /// The descriptor this declaration relates to.
50        /// </summary>
51        public IDescriptor Descriptor { get; }
52
53        /// <summary>
54        /// The start line of the declaration within the source file. This value is 1-based.
55        /// </summary>
56        public int StartLine { get; }
57        /// <summary>
58        /// The start column of the declaration within the source file. This value is 1-based.
59        /// </summary>
60        public int StartColumn { get; }
61
62        /// <summary>
63        /// // The end line of the declaration within the source file. This value is 1-based.
64        /// </summary>
65        public int EndLine { get; }
66        /// <summary>
67        /// The end column of the declaration within the source file. This value is 1-based, and
68        /// exclusive. (The final character of the declaration is on the column before this value.)
69        /// </summary>
70        public int EndColumn { get; }
71
72        /// <summary>
73        /// Comments appearing before the declaration. Never null, but may be empty. Multi-line comments
74        /// are represented as a newline-separated string. Leading whitespace and the comment marker ("//")
75        /// are removed from each line.
76        /// </summary>
77        public string LeadingComments { get; }
78
79        /// <summary>
80        /// Comments appearing after the declaration. Never null, but may be empty. Multi-line comments
81        /// are represented as a newline-separated string. Leading whitespace and the comment marker ("//")
82        /// are removed from each line.
83        /// </summary>
84        public string TrailingComments { get; }
85
86        /// <summary>
87        /// Comments appearing before the declaration, but separated from it by blank
88        /// lines. Each string represents a newline-separated paragraph of comments.
89        /// Leading whitespace and the comment marker ("//") are removed from each line.
90        /// The list is never null, but may be empty. Likewise each element is never null, but may be empty.
91        /// </summary>
92        public IReadOnlyList<string> LeadingDetachedComments { get; }
93
94        private DescriptorDeclaration(IDescriptor descriptor, Location location)
95        {
96            // TODO: Validation
97            Descriptor = descriptor;
98            bool hasEndLine = location.Span.Count == 4;
99            // Lines and columns are 0-based in the proto.
100            StartLine = location.Span[0] + 1;
101            StartColumn = location.Span[1] + 1;
102            EndLine = hasEndLine ? location.Span[2] + 1 : StartLine;
103            EndColumn = location.Span[hasEndLine ? 3 : 2] + 1;
104            LeadingComments = location.LeadingComments;
105            TrailingComments = location.TrailingComments;
106            LeadingDetachedComments = new ReadOnlyCollection<string>(location.LeadingDetachedComments.ToList());
107        }
108
109        internal static DescriptorDeclaration FromProto(IDescriptor descriptor, Location location) =>
110            new DescriptorDeclaration(descriptor, location);
111    }
112}
113