Welcome to mirror list, hosted at ThFree Co, Russian Federation.

TokenComparer.cs « Util « CSharpBinding « addins « src « main - github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2fe8d6f4120d822da25a4fd7311c2393dc65bd80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// 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.Collections.Generic;
using System.Globalization;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace ICSharpCode.NRefactory6.CSharp
{
	internal class TokenComparer : IComparer<SyntaxToken>
	{
		private const string SystemNamespace = "System";

		public static readonly IComparer<SyntaxToken> NormalInstance = new TokenComparer(specialCaseSystem: false);
		public static readonly IComparer<SyntaxToken> SystemFirstInstance = new TokenComparer(specialCaseSystem: true);

		private readonly bool _specialCaseSystem;

		private TokenComparer(bool specialCaseSystem)
		{
			_specialCaseSystem = specialCaseSystem;
		}

		private static bool IsSystem(string s)
		{
			return s == SystemNamespace;
		}

		public int Compare(SyntaxToken x, SyntaxToken y)
		{
			if (_specialCaseSystem &&
				x.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.UsingKeyword, SyntaxKind.StaticKeyword) &&
				y.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.UsingKeyword, SyntaxKind.StaticKeyword))
			{
				var token1IsSystem = IsSystem(x.ValueText);
				var token2IsSystem = IsSystem(y.ValueText);

				if (token1IsSystem && !token2IsSystem)
				{
					return -1;
				}
				else if (!token1IsSystem && token2IsSystem)
				{
					return 1;
				}
			}

			return CompareWorker(x, y);
		}

		private int CompareWorker(SyntaxToken x, SyntaxToken y)
		{
			if (x == y)
			{
				return 0;
			}

			// By using 'ValueText' we get the value that is normalized.  i.e.
			// @class will be 'class', and unicode escapes will be converted
			// to actual unicode.  This allows sorting to work properly across
			// tokens that have different source representations, but which
			// mean the same thing.
			var string1 = x.ValueText;
			var string2 = y.ValueText;

			// First check in a case insensitive manner.  This will put 
			// everything that starts with an 'a' or 'A' above everything
			// that starts with a 'b' or 'B'.
			var compare = CultureInfo.InvariantCulture.CompareInfo.Compare(string1, string2,
				CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreWidth);
			if (compare != 0)
			{
				return compare;
			}

			// Now, once we've grouped such that 'a' words and 'A' words are
			// together, sort such that 'a' words come before 'A' words.
			return CultureInfo.InvariantCulture.CompareInfo.Compare(string1, string2,
				CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreWidth);
		}
	}
}