@@ -105,7 +105,7 @@ bool DeclarationContainer::registerDeclaration(
105
105
return true ;
106
106
}
107
107
108
- std:: vector<Declaration const *> DeclarationContainer::resolveName (ASTString const & _name, bool _recursive) const
108
+ vector<Declaration const *> DeclarationContainer::resolveName (ASTString const & _name, bool _recursive) const
109
109
{
110
110
solAssert (!_name.empty (), " Attempt to resolve empty name." );
111
111
auto result = m_declarations.find (_name);
@@ -115,3 +115,64 @@ std::vector<Declaration const*> DeclarationContainer::resolveName(ASTString cons
115
115
return m_enclosingContainer->resolveName (_name, true );
116
116
return vector<Declaration const *>({});
117
117
}
118
+
119
+ vector<ASTString> DeclarationContainer::similarNames (ASTString const & _name) const
120
+ {
121
+ vector<ASTString> similar;
122
+
123
+ for (auto const & declaration: m_declarations)
124
+ {
125
+ string const & declarationName = declaration.first ;
126
+ if (DeclarationContainer::areSimilarNames (_name, declarationName))
127
+ similar.push_back (declarationName);
128
+ }
129
+
130
+ if (m_enclosingContainer)
131
+ {
132
+ vector<ASTString> enclosingSimilar = m_enclosingContainer->similarNames (_name);
133
+ similar.insert (similar.end (), enclosingSimilar.begin (), enclosingSimilar.end ());
134
+ }
135
+
136
+ return similar;
137
+ }
138
+
139
+ bool DeclarationContainer::areSimilarNames (ASTString const & _name1, ASTString const & _name2)
140
+ {
141
+ if (_name1 == _name2)
142
+ return true ;
143
+
144
+ size_t n1 = _name1.size (), n2 = _name2.size ();
145
+ vector<vector<size_t >> dp (n1 + 1 , vector<size_t >(n2 + 1 ));
146
+
147
+ // In this dp formulation of Damerau–Levenshtein distance we are assuming that the strings are 1-based to make base case storage easier.
148
+ // So index accesser to _name1 and _name2 have to be adjusted accordingly
149
+ for (size_t i1 = 0 ; i1 <= n1; ++i1)
150
+ {
151
+ for (size_t i2 = 0 ; i2 <= n2; ++i2)
152
+ {
153
+ if (min (i1, i2) == 0 ) // base case
154
+ dp[i1][i2] = max (i1, i2);
155
+ else
156
+ {
157
+ dp[i1][i2] = min (dp[i1-1 ][i2] + 1 , dp[i1][i2-1 ] + 1 );
158
+ // Deletion and insertion
159
+ if (_name1[i1-1 ] == _name2[i2-1 ])
160
+ // Same chars, can skip
161
+ dp[i1][i2] = min (dp[i1][i2], dp[i1-1 ][i2-1 ]);
162
+ else
163
+ // Different chars so try substitution
164
+ dp[i1][i2] = min (dp[i1][i2], dp[i1-1 ][i2-1 ] + 1 );
165
+
166
+ if (i1 > 1 && i2 > 1 && _name1[i1-1 ] == _name2[i2-2 ] && _name1[i1-2 ] == _name2[i2-1 ])
167
+ // Try transposing
168
+ dp[i1][i2] = min (dp[i1][i2], dp[i1-2 ][i2-2 ] + 1 );
169
+ }
170
+ }
171
+ }
172
+
173
+ size_t distance = dp[n1][n2];
174
+
175
+ // If distance is not greater than MAXIMUM_DISTANCE, and distance is strictly less than length of both names,
176
+ // they can be considered similar this is to avoid irrelevant suggestions
177
+ return distance <= MAXIMUM_DISTANCE && distance < n1 && distance < n2;
178
+ }
0 commit comments