Branch data Line data Source code
1 : : /* Find near-matches for identifiers.
2 : : Copyright (C) 2015-2025 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 edit distance between two identifiers. */
31 : :
32 : : edit_distance_t
33 : 0 : get_edit_distance (tree ident_s, tree ident_t)
34 : : {
35 : 0 : gcc_assert (TREE_CODE (ident_s) == IDENTIFIER_NODE);
36 : 0 : gcc_assert (TREE_CODE (ident_t) == IDENTIFIER_NODE);
37 : :
38 : 0 : return get_edit_distance (IDENTIFIER_POINTER (ident_s),
39 : 0 : IDENTIFIER_LENGTH (ident_s),
40 : 0 : IDENTIFIER_POINTER (ident_t),
41 : 0 : 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 : 797 : find_closest_identifier (tree target, const auto_vec<tree> *candidates)
54 : : {
55 : 797 : gcc_assert (TREE_CODE (target) == IDENTIFIER_NODE);
56 : :
57 : 797 : best_match<tree, tree> bm (target);
58 : 797 : int i;
59 : 797 : tree identifier;
60 : 3453 : FOR_EACH_VEC_ELT (*candidates, i, identifier)
61 : : {
62 : 1859 : gcc_assert (TREE_CODE (identifier) == IDENTIFIER_NODE);
63 : 1859 : bm.consider (identifier);
64 : : }
65 : :
66 : 797 : return bm.get_best_meaningful_candidate ();
67 : : }
68 : :
69 : : #if CHECKING_P
70 : :
71 : : namespace selftest {
72 : :
73 : : /* Selftests. */
74 : :
75 : : /* Verify that find_closest_identifier is sane. */
76 : :
77 : : static void
78 : 4 : test_find_closest_identifier ()
79 : : {
80 : 4 : auto_vec<tree> candidates;
81 : :
82 : : /* Verify that it can handle an empty vec. */
83 : 4 : ASSERT_EQ (NULL, find_closest_identifier (get_identifier (""), &candidates));
84 : :
85 : : /* Verify that it works sanely for non-empty vecs. */
86 : 4 : tree apple = get_identifier ("apple");
87 : 4 : tree banana = get_identifier ("banana");
88 : 4 : tree cherry = get_identifier ("cherry");
89 : 4 : candidates.safe_push (apple);
90 : 4 : candidates.safe_push (banana);
91 : 4 : candidates.safe_push (cherry);
92 : :
93 : 4 : ASSERT_EQ (apple, find_closest_identifier (get_identifier ("app"),
94 : : &candidates));
95 : 4 : ASSERT_EQ (banana, find_closest_identifier (get_identifier ("banyan"),
96 : : &candidates));
97 : 4 : ASSERT_EQ (cherry, find_closest_identifier (get_identifier ("berry"),
98 : : &candidates));
99 : 4 : ASSERT_EQ (NULL,
100 : : find_closest_identifier (get_identifier ("not like the others"),
101 : : &candidates));
102 : 4 : }
103 : :
104 : : /* Run all of the selftests within this file. */
105 : :
106 : : void
107 : 4 : spellcheck_tree_cc_tests ()
108 : : {
109 : 4 : test_find_closest_identifier ();
110 : 4 : }
111 : :
112 : : } // namespace selftest
113 : :
114 : : #endif /* #if CHECKING_P */
|