Mercurial > hg > CbC > CbC_gcc
comparison gcc/spellcheck-tree.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Find near-matches for identifiers. | |
2 Copyright (C) 2015-2017 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
23 #include "tm.h" | |
24 #include "tree.h" | |
25 #include "cpplib.h" | |
26 #include "spellcheck-tree.h" | |
27 #include "selftest.h" | |
28 #include "stringpool.h" | |
29 | |
30 /* Calculate Levenshtein distance between two identifiers. */ | |
31 | |
32 edit_distance_t | |
33 levenshtein_distance (tree ident_s, tree ident_t) | |
34 { | |
35 gcc_assert (TREE_CODE (ident_s) == IDENTIFIER_NODE); | |
36 gcc_assert (TREE_CODE (ident_t) == IDENTIFIER_NODE); | |
37 | |
38 return levenshtein_distance (IDENTIFIER_POINTER (ident_s), | |
39 IDENTIFIER_LENGTH (ident_s), | |
40 IDENTIFIER_POINTER (ident_t), | |
41 IDENTIFIER_LENGTH (ident_t)); | |
42 } | |
43 | |
44 /* Given TARGET, an identifier, and CANDIDATES, a vec of identifiers, | |
45 determine which element within CANDIDATES has the lowest edit | |
46 distance to TARGET. If there are multiple elements with the | |
47 same minimal distance, the first in the vector wins. | |
48 | |
49 If more than half of the letters were misspelled, the suggestion is | |
50 likely to be meaningless, so return NULL_TREE for this case. */ | |
51 | |
52 tree | |
53 find_closest_identifier (tree target, const auto_vec<tree> *candidates) | |
54 { | |
55 gcc_assert (TREE_CODE (target) == IDENTIFIER_NODE); | |
56 | |
57 best_match<tree, tree> bm (target); | |
58 int i; | |
59 tree identifier; | |
60 FOR_EACH_VEC_ELT (*candidates, i, identifier) | |
61 { | |
62 gcc_assert (TREE_CODE (identifier) == IDENTIFIER_NODE); | |
63 bm.consider (identifier); | |
64 } | |
65 | |
66 return bm.get_best_meaningful_candidate (); | |
67 } | |
68 | |
69 /* A callback for cpp_forall_identifiers, for use by best_macro_match's ctor. | |
70 Process HASHNODE and update the best_macro_match instance pointed to be | |
71 USER_DATA. */ | |
72 | |
73 static int | |
74 find_closest_macro_cpp_cb (cpp_reader *, cpp_hashnode *hashnode, | |
75 void *user_data) | |
76 { | |
77 if (hashnode->type != NT_MACRO) | |
78 return 1; | |
79 | |
80 best_macro_match *bmm = (best_macro_match *)user_data; | |
81 bmm->consider (hashnode); | |
82 | |
83 /* Keep iterating. */ | |
84 return 1; | |
85 } | |
86 | |
87 /* Constructor for best_macro_match. | |
88 Use find_closest_macro_cpp_cb to find the closest matching macro to | |
89 NAME within distance < best_distance_so_far. */ | |
90 | |
91 best_macro_match::best_macro_match (tree goal, | |
92 edit_distance_t best_distance_so_far, | |
93 cpp_reader *reader) | |
94 : best_match <goal_t, candidate_t> (goal, best_distance_so_far) | |
95 { | |
96 cpp_forall_identifiers (reader, find_closest_macro_cpp_cb, this); | |
97 } | |
98 | |
99 #if CHECKING_P | |
100 | |
101 namespace selftest { | |
102 | |
103 /* Selftests. */ | |
104 | |
105 /* Verify that find_closest_identifier is sane. */ | |
106 | |
107 static void | |
108 test_find_closest_identifier () | |
109 { | |
110 auto_vec<tree> candidates; | |
111 | |
112 /* Verify that it can handle an empty vec. */ | |
113 ASSERT_EQ (NULL, find_closest_identifier (get_identifier (""), &candidates)); | |
114 | |
115 /* Verify that it works sanely for non-empty vecs. */ | |
116 tree apple = get_identifier ("apple"); | |
117 tree banana = get_identifier ("banana"); | |
118 tree cherry = get_identifier ("cherry"); | |
119 candidates.safe_push (apple); | |
120 candidates.safe_push (banana); | |
121 candidates.safe_push (cherry); | |
122 | |
123 ASSERT_EQ (apple, find_closest_identifier (get_identifier ("app"), | |
124 &candidates)); | |
125 ASSERT_EQ (banana, find_closest_identifier (get_identifier ("banyan"), | |
126 &candidates));; | |
127 ASSERT_EQ (cherry, find_closest_identifier (get_identifier ("berry"), | |
128 &candidates)); | |
129 ASSERT_EQ (NULL, | |
130 find_closest_identifier (get_identifier ("not like the others"), | |
131 &candidates)); | |
132 } | |
133 | |
134 /* Run all of the selftests within this file. */ | |
135 | |
136 void | |
137 spellcheck_tree_c_tests () | |
138 { | |
139 test_find_closest_identifier (); | |
140 } | |
141 | |
142 } // namespace selftest | |
143 | |
144 #endif /* #if CHECKING_P */ |