public void Tokenization()
        {
            string source = "void f(int x); void g(int x) { f(x); }";

            using (var empty = disposables.WriteToEmpty(source))
            {
                var file  = empty.GetFile(TestFiles.Empty);
                var range = SourceRange.Create(
                    file.GetLocationFromOffset((uint)source.IndexOf("f(x)")),
                    file.GetLocationFromOffset((uint)(source.IndexOf(" }"))));
                var tokens = empty.Tokenize(range);
                CollectionAssert.AreEqual(
                    new[] { "f", "(", "x", ")", ";" },
                    tokens.ToArray(token => token.GetSpelling()));

                Assert.AreEqual(TokenKind.Identifier, tokens[0].GetKind());
                Assert.AreEqual("f", tokens[0].GetSpelling());
                Assert.AreEqual(
                    file.GetLocationFromOffset((uint)source.IndexOf("f(x)")),
                    tokens[0].GetLocation());
                Assert.AreEqual(
                    (uint)source.IndexOf("f(x)"),
                    tokens[0].GetExtent().GetStart().Offset);
                Assert.AreEqual(
                    (uint)source.IndexOf("f(x)") + 1,
                    tokens[0].GetExtent().GetEnd().Offset);

                Assert.AreEqual(TokenKind.Punctuation, tokens[1].GetKind());
                Assert.AreEqual("(", tokens[1].GetSpelling());
                Assert.AreEqual(TokenKind.Identifier, tokens[2].GetKind());
                Assert.AreEqual("x", tokens[2].GetSpelling());
                Assert.AreEqual(TokenKind.Punctuation, tokens[3].GetKind());
                Assert.AreEqual(")", tokens[3].GetSpelling());
            }
        }
        /// <summary>
        /// Gets a source range associated with the diagnostic.
        /// </summary>
        /// <param name="index">The zero-based index specifying which range to extract.</param>
        /// <returns>
        /// The requested source range, or null if <paramref name="index"/> is invalid.
        /// </returns>
        /// <remarks>
        /// A diagnostic's source ranges highlight important elements in the source code. On the
        /// command line, Clang displays source ranges by underlining them with '~' characters.
        /// </remarks>
        public SourceRange GetRange(uint index)
        {
            ThrowIfDisposed();

            var cxSourceRange = NativeMethods.clang_getDiagnosticRange(Ptr, index);

            return(SourceRange.Create(cxSourceRange, TranslationUnit));
        }
        public void GetStartAndGetEndReturnOriginalLocations()
        {
            var add = disposables.Add;

            var file  = add.GetFile(TestFiles.AddSource);
            var begin = file.GetLocation(1, 1);
            var end   = file.GetLocation(2, 1);
            var range = SourceRange.Create(begin, end);

            Assert.AreEqual(begin, range.GetStart());
            Assert.AreEqual(end, range.GetEnd());
        }
        public void CreateInvalidRangeReturnsNull()
        {
            var add = disposables.Add;

            var file  = add.GetFile(TestFiles.AddSource);
            var range = SourceRange.Create(file.GetLocation(1, 1), file.GetLocation(2, 1));

            Assert.IsNotNull(range);

            range = SourceRange.Create(
                add.GetFile(TestFiles.AddHeader).GetLocation(1, 1),
                file.GetLocation(1, 1));
            Assert.IsNull(range);
        }
        /// <summary>
        /// Gets the replacement information for a fix-it.
        /// </summary>
        /// <param name="index">The zero-based index of the fix-it.</param>
        /// <returns>
        /// replacementRange: The source range whose contents will be replaced with the returned
        /// replacement string. Note that source ranges are half-open ranges [a, b), so the source
        /// code should be replaced from a and up to (but not including) b.<para/>
        /// replacementText: A string containing text that should be replace the source code
        /// indicated by the replacementRange.
        /// </returns>
        /// <remarks>
        /// Fix-its are described in terms of a source range whose contents should be replaced by a
        /// string. This approach generalizes over three kinds of operations: removal of source
        /// code (the range covers the code to be removed and the replacement string is empty),
        /// replacement of source code (the range covers the code to be replaced and the
        /// replacement string provides the new code), and insertion (both the start and end of the
        /// range point at the insertion location, and the replacement string provides the text to
        /// insert).
        /// </remarks>
        public (SourceRange replacementRange, string replacementText) GetFixIt(uint index)
        {
            ThrowIfDisposed();

            CXSourceRange cxSourceRange;
            var           cxString = NativeMethods.clang_getDiagnosticFixIt(
                Ptr,
                index,
                &cxSourceRange);
            var replacementRange = SourceRange.Create(cxSourceRange, TranslationUnit);

            using (var str = new String(cxString))
            {
                return(replacementRange : replacementRange, replacementText : str.ToString());
            }
        }