Skip to content

Commit 4a4e4fc

Browse files
authored
Merge master into BETA_JAVA27 branch
2 parents 68a8289 + a104ded commit 4a4e4fc

68 files changed

Lines changed: 2712 additions & 117 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

org.eclipse.jdt.core.manipulation/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Bundle-Localization: plugin
1010
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.31.0,4.0.0)",
1111
org.eclipse.core.resources;bundle-version="[3.20.0,4.0.0)",
1212
org.eclipse.ltk.core.refactoring;bundle-version="[3.14.0,4.0.0)",
13-
org.eclipse.jdt.core;bundle-version="[3.40.0,4.0.0)",
13+
org.eclipse.jdt.core;bundle-version="[3.46.0,4.0.0)",
1414
org.eclipse.core.expressions;bundle-version="[3.9.0,4.0.0)",
1515
org.eclipse.text;bundle-version="[3.14.0,4.0.0)",
1616
org.eclipse.jdt.launching;bundle-version="3.23.0",

org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/core/manipulation/internal/javadoc/CoreJavaDocSnippetStringEvaluator.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,7 @@ protected String getModifiedString(String str, List<TagElement> tags) {
202202
}
203203

204204
private String getString(String str, List<ActionElement> actionElements) {
205-
String modifiedStr= str.replaceAll(">", "&gt;"); //$NON-NLS-1$ //$NON-NLS-2$
206-
modifiedStr= modifiedStr.replaceAll("<", "&lt;"); //$NON-NLS-1$ //$NON-NLS-2$
205+
String modifiedStr = str;
207206
List<StringItem> items= new ArrayList<>();
208207
for (ActionElement actElem : actionElements) {
209208
StringItem startItem= new StringItem(actElem.start, actElem.startTag);
@@ -236,6 +235,14 @@ private String getString(String str, List<ActionElement> actionElements) {
236235
items.add(startItem);
237236
}
238237
}
238+
items.sort((a, b) -> {
239+
if (b.index != a.index) {
240+
return Integer.compare(b.index, a.index);
241+
}
242+
boolean aIsEnd = a.tag.startsWith("</"); //$NON-NLS-1$
243+
boolean bIsEnd = b.tag.startsWith("</"); //$NON-NLS-1$
244+
return Boolean.compare(bIsEnd, aIsEnd);
245+
});
239246
for (StringItem item : items) {
240247
modifiedStr= modifiedStr.substring(0, item.index) + item.tag + modifiedStr.substring(item.index);
241248
}

org.eclipse.jdt.core.manipulation/common/org/eclipse/jdt/internal/ui/text/correction/UnresolvedElementsBaseSubProcessor.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,8 @@ private void addSimilarTypeProposals(int kind, ICompilationUnit cu, Name node, i
957957
String resolvedTypeName= null;
958958
ITypeBinding binding= ASTResolving.guessBindingForTypeReference(node);
959959
ITypeBinding simpleBinding= null;
960-
if (binding != null) {
960+
if (binding != null &&
961+
(!binding.getQualifiedName().equals("java.lang.Object") || elements.length == 0)) { //$NON-NLS-1$
961962
simpleBinding= binding;
962963
if (simpleBinding.isArray()) {
963964
simpleBinding= simpleBinding.getElementType();
@@ -1045,7 +1046,7 @@ private void addSimilarTypeProposals(int kind, ICompilationUnit cu, Name node, i
10451046
}
10461047
}
10471048
if (elements.length == 0) {
1048-
collectRequiresModuleProposals(cu, node, IProposalRelevance.IMPORT_NOT_FOUND_ADD_REQUIRES_MODULE, proposals, true);
1049+
collectRequiresModuleProposals(cu, node, IProposalRelevance.IMPORT_NOT_FOUND_ADD_REQUIRES_MODULE + 100, proposals, true);
10491050
}
10501051
}
10511052

@@ -1094,7 +1095,7 @@ private T getCompositeChangeProposal(ChangeCorrectionProposalCore proposal) thro
10941095
String moduleRequiresChangeName= change.getName();
10951096
moduleRequiresChangeName= moduleRequiresChangeName.substring(0, 1).toLowerCase() + moduleRequiresChangeName.substring(1);
10961097
String changeName= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_combine_two_proposals_info, new String[] { importChangeName, moduleRequiresChangeName });
1097-
compositeProposal= new ChangeCorrectionProposalCore(changeName, null, IProposalRelevance.IMPORT_NOT_FOUND_ADD_REQUIRES_MODULE) {
1098+
compositeProposal= new ChangeCorrectionProposalCore(changeName, null, aicpc.getRelevance()) {
10981099
@Override
10991100
protected Change createChange() throws CoreException {
11001101
return new CompositeChange(changeName, new Change[] { change, importChange });

org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/callhierarchy/CallHierarchyCore.java

Lines changed: 219 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,30 @@
2323
import java.util.List;
2424
import java.util.StringTokenizer;
2525

26+
import org.eclipse.core.runtime.CoreException;
27+
import org.eclipse.core.runtime.IProgressMonitor;
2628
import org.eclipse.core.runtime.NullProgressMonitor;
29+
import org.eclipse.core.runtime.OperationCanceledException;
2730

2831
import org.eclipse.jdt.core.IJavaElement;
2932
import org.eclipse.jdt.core.IMember;
3033
import org.eclipse.jdt.core.IMethod;
3134
import org.eclipse.jdt.core.IModuleDescription;
3235
import org.eclipse.jdt.core.IType;
36+
import org.eclipse.jdt.core.ITypeHierarchy;
3337
import org.eclipse.jdt.core.ITypeRoot;
38+
import org.eclipse.jdt.core.JavaCore;
3439
import org.eclipse.jdt.core.JavaModelException;
40+
import org.eclipse.jdt.core.Signature;
3541
import org.eclipse.jdt.core.dom.ASTParser;
3642
import org.eclipse.jdt.core.dom.CompilationUnit;
3743
import org.eclipse.jdt.core.manipulation.JavaManipulation;
44+
import org.eclipse.jdt.core.search.IJavaSearchConstants;
3845
import org.eclipse.jdt.core.search.IJavaSearchScope;
3946
import org.eclipse.jdt.core.search.SearchEngine;
47+
import org.eclipse.jdt.core.search.SearchMatch;
48+
import org.eclipse.jdt.core.search.SearchPattern;
49+
import org.eclipse.jdt.core.search.SearchRequestor;
4050

4151
import org.eclipse.jdt.internal.core.manipulation.JavaManipulationPlugin;
4252
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
@@ -297,18 +307,226 @@ private static StringMatcher[] parseList(String listString) {
297307
static CompilationUnit getCompilationUnitNode(IMember member, boolean resolveBindings) {
298308
ITypeRoot typeRoot= member.getTypeRoot();
299309
try {
300-
if (typeRoot.exists() && typeRoot.getBuffer() != null) {
310+
if (typeRoot != null && typeRoot.exists() && typeRoot.getBuffer() != null
311+
&& JavaCore.isJavaLikeFileName(typeRoot.getElementName())) {
301312
ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
302313
parser.setSource(typeRoot);
303314
parser.setResolveBindings(resolveBindings);
304315
return (CompilationUnit) parser.createAST(null);
305316
}
306317
} catch (JavaModelException e) {
307318
JavaManipulationPlugin.log(e);
319+
} catch (ClassCastException e) {
320+
// Non-standard ITypeRoot (e.g. from a contributed search participant)
321+
// that does not implement the internal compiler interfaces required
322+
// by ASTParser — fall through and return null
323+
JavaManipulationPlugin.log(e);
308324
}
309325
return null;
310326
}
311327

328+
/**
329+
* Searches for the first {@link IMember} declaration matching the given
330+
* name, element type, and optional call-site constraints.
331+
*
332+
* <p>Filters are applied in order of cheapness: argument count first
333+
* (O(1)), then declaring type (string compare or hierarchy lookup),
334+
* then argument types (per-parameter type compatibility check).
335+
*
336+
* @param elementName the simple name to search for
337+
* @param searchFor one of {@link IJavaSearchConstants#METHOD},
338+
* {@link IJavaSearchConstants#FIELD}, or
339+
* {@link IJavaSearchConstants#TYPE}
340+
* @param scope the search scope
341+
* @param monitor progress monitor, may be {@code null}
342+
* @param expectedArgCount expected argument count, or {@code -1} to skip
343+
* @param receiverTypeFQN receiver type FQN to match declaring type
344+
* against, or {@code null} to skip
345+
* @param declaringTypeCandidates FQN candidates for the declaring type,
346+
* or {@code null} to skip
347+
* @param expectedArgTypes argument type FQNs from the call site (may
348+
* contain {@code "UNKNOWN"} entries), or {@code null} to skip
349+
* @return the first matching member, or {@code null} if none found
350+
*/
351+
static IMember findFirstDeclaration(String elementName, int searchFor,
352+
IJavaSearchScope scope, IProgressMonitor monitor,
353+
int expectedArgCount, String receiverTypeFQN,
354+
List<String> declaringTypeCandidates,
355+
String[] expectedArgTypes) {
356+
SearchPattern pattern= SearchPattern.createPattern(
357+
elementName, searchFor,
358+
IJavaSearchConstants.DECLARATIONS,
359+
SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
360+
if (pattern == null)
361+
return null;
362+
final IMember[] result= { null };
363+
try {
364+
new SearchEngine().search(pattern,
365+
SearchEngine.getSearchParticipants(), scope,
366+
new SearchRequestor() {
367+
@Override
368+
public void acceptSearchMatch(SearchMatch match) {
369+
if (result[0] != null) {
370+
return;
371+
}
372+
if (!(match.getElement() instanceof IMember m)) {
373+
return;
374+
}
375+
if (m instanceof IMethod method
376+
&& !matchesMethod(method,
377+
expectedArgCount,
378+
expectedArgTypes)) {
379+
return;
380+
}
381+
if (m.getDeclaringType() != null) {
382+
String declFQN= m.getDeclaringType()
383+
.getFullyQualifiedName();
384+
if (receiverTypeFQN != null
385+
&& !isTypeOrSupertype(declFQN,
386+
receiverTypeFQN, m)) {
387+
return;
388+
}
389+
if (declaringTypeCandidates != null
390+
&& !declaringTypeCandidates.isEmpty()
391+
&& !declaringTypeCandidates
392+
.contains(declFQN)) {
393+
return;
394+
}
395+
}
396+
result[0]= m;
397+
throw new OperationCanceledException();
398+
}
399+
}, monitor);
400+
} catch (OperationCanceledException e) {
401+
// short-circuit: first match found
402+
} catch (CoreException e) {
403+
JavaManipulationPlugin.log(e);
404+
}
405+
return result[0];
406+
}
407+
408+
/**
409+
* Checks if a candidate method matches the expected argument count
410+
* and types from the call site.
411+
*/
412+
private static boolean matchesMethod(IMethod method,
413+
int expectedArgCount, String[] expectedArgTypes) {
414+
int paramCount= method.getNumberOfParameters();
415+
// Argument count filter
416+
if (expectedArgCount >= 0
417+
&& paramCount != expectedArgCount) {
418+
String[] sigs= method.getParameterTypes();
419+
if (paramCount == 0
420+
|| Signature.getArrayCount(
421+
sigs[paramCount - 1]) == 0
422+
|| expectedArgCount < paramCount - 1) {
423+
return false;
424+
}
425+
}
426+
// Argument type filter
427+
if (expectedArgTypes != null
428+
&& expectedArgTypes.length > 0
429+
&& expectedArgTypes.length == paramCount) {
430+
String[] paramSigs= method.getParameterTypes();
431+
IType declType= method.getDeclaringType();
432+
for (int i= 0; i < paramCount; i++) {
433+
String callSiteType= expectedArgTypes[i];
434+
if ("UNKNOWN".equals(callSiteType)) { //$NON-NLS-1$
435+
continue;
436+
}
437+
String paramFQN= resolveParameterType(
438+
paramSigs[i], declType);
439+
if (paramFQN == null) {
440+
continue;
441+
}
442+
if (!isTypeCompatible(callSiteType,
443+
paramFQN, method)) {
444+
return false;
445+
}
446+
}
447+
}
448+
return true;
449+
}
450+
451+
/**
452+
* Resolves a JDT parameter type signature to a fully qualified
453+
* name using the declaring type's context.
454+
*/
455+
private static String resolveParameterType(String paramSig,
456+
IType declaringType) {
457+
try {
458+
String erasure= Signature.getTypeErasure(paramSig);
459+
String simpleName= Signature.toString(erasure);
460+
if (simpleName.contains(".")) { //$NON-NLS-1$
461+
return simpleName;
462+
}
463+
if (declaringType == null) {
464+
return null;
465+
}
466+
String[][] resolved= declaringType.resolveType(simpleName);
467+
if (resolved != null && resolved.length > 0) {
468+
String pkg= resolved[0][0];
469+
String name= resolved[0][1];
470+
return pkg.isEmpty() ? name : pkg + "." + name; //$NON-NLS-1$
471+
}
472+
} catch (JavaModelException e) {
473+
// can't resolve
474+
}
475+
return null;
476+
}
477+
478+
/**
479+
* Checks if the call-site argument type is compatible with the
480+
* parameter type. The argument type must be the same as or a
481+
* subtype of the parameter type.
482+
*/
483+
private static boolean isTypeCompatible(String argTypeFQN,
484+
String paramTypeFQN, IMember context) {
485+
if (argTypeFQN.equals(paramTypeFQN)) {
486+
return true;
487+
}
488+
// The parameter type is a supertype of the argument type
489+
// (e.g., param is Object, arg is String) — check if
490+
// argType is-a paramType
491+
return isTypeOrSupertype(paramTypeFQN, argTypeFQN, context);
492+
}
493+
494+
/**
495+
* Checks if {@code candidateFQN} is the same as or a supertype of
496+
* {@code receiverFQN}. Uses the JDT type hierarchy when available.
497+
*/
498+
private static boolean isTypeOrSupertype(String candidateFQN,
499+
String receiverFQN, IMember context) {
500+
if (candidateFQN.equals(receiverFQN)) {
501+
return true;
502+
}
503+
// Check common base types without hierarchy lookup
504+
if ("java.lang.Object".equals(candidateFQN)) { //$NON-NLS-1$
505+
return true;
506+
}
507+
// Try type hierarchy for precise check
508+
try {
509+
if (context.getJavaProject() != null) {
510+
IType receiverType= context.getJavaProject()
511+
.findType(receiverFQN);
512+
if (receiverType != null) {
513+
ITypeHierarchy hierarchy=
514+
receiverType.newSupertypeHierarchy(null);
515+
for (IType superType
516+
: hierarchy.getAllSupertypes(receiverType)) {
517+
if (candidateFQN.equals(
518+
superType.getFullyQualifiedName())) {
519+
return true;
520+
}
521+
}
522+
}
523+
}
524+
} catch (JavaModelException e) {
525+
JavaManipulationPlugin.log(e);
526+
}
527+
return false;
528+
}
529+
312530
public static boolean isPossibleInputElement(Object element){
313531
if (! (element instanceof IMember))
314532
return false;

0 commit comments

Comments
 (0)