From f4be3efc315f4bd8414049bb9e878f919b1b50b8 Mon Sep 17 00:00:00 2001 From: Woongsik Choi Date: Mon, 10 Sep 2012 04:01:15 +0900 Subject: [PATCH] [Title] Changes for hoisting of functions are roll backed. [Type] BugFix [Module] JSDT [Priority] [CQ#] [Redmine#] 6450 [Problem] [Cause] [Solution] [TestCase] --- .../compiler/lookup/SourceTypeBinding.java | 197 ++++++++++++++++----- 1 file changed, 156 insertions(+), 41 deletions(-) diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java index b1ade09..03ed1dd 100644 --- a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/lookup/SourceTypeBinding.java @@ -794,52 +794,167 @@ public class SourceTypeBinding extends ReferenceBinding { } // find & report collision cases - MethodBinding prevMethod = null; - int prevIndex = -1; - for (int i=0, length = this.methods.length; i < length; i++) { + + boolean complyTo15 = (this.scope != null && this.scope + .compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5); + for (int i = 0, length = this.methods.length; i < length; i++) { MethodBinding method = resolvedMethods[i]; - if (method == null) { - continue; - } - - if (prevMethod == null || !CharOperation.equals(prevMethod.selector, method.selector)) { - prevMethod = method; - prevIndex = i; + if (method == null) continue; + char[] selector = method.selector; + AbstractMethodDeclaration methodDecl = null; + nextSibling: for (int j = i + 1; j < length; j++) { + MethodBinding method2 = resolvedMethods[j]; + if (method2 == null) + continue nextSibling; + if (!CharOperation.equals(selector, method2.selector)) + break nextSibling; // methods with same selector are + // contiguous + + if (complyTo15 && method.returnType != null + && method2.returnType != null) { + // 8.4.2, for collision to be detected between m1 + // and m2: + // signature(m1) == signature(m2) i.e. same arity, + // same type parameter count, can be substituted + // signature(m1) == erasure(signature(m2)) or + // erasure(signature(m1)) == signature(m2) + TypeBinding[] params1 = method.parameters; + TypeBinding[] params2 = method2.parameters; + int pLength = params1.length; + if (pLength != params2.length) + continue nextSibling; + + MethodBinding subMethod = method2; + boolean equalParams = method + .areParametersEqual(subMethod); + if (equalParams) { + // duplicates regardless of return types + } else if (method.returnType == subMethod.returnType + && (equalParams || method + .areParametersEqual(method2))) { + // name clash for sure if not duplicates, report + // as duplicates + } else if (pLength > 0) { + // check to see if the erasure of either method + // is equal to the other + int index = pLength; + for (; --index >= 0;) { + if (params1[index] != params2[index]) + break; + } + if (index >= 0 && index < pLength) { + for (index = pLength; --index >= 0;) + if (params1[index] != params2[index]) + break; + } + if (index >= 0) + continue nextSibling; + } + } else if (!method.areParametersEqual(method2)) { // prior + // to + // 1.5, + // parameter + // identity + // meant + // a + // collision + // case + continue nextSibling; + } + // report duplicate + if (methodDecl == null) { + methodDecl = method.sourceMethod(); // cannot be + // retrieved + // after binding + // is lost & may + // still be null + // if method is + // special + if (methodDecl != null + && methodDecl.binding != null) { // ensure + // its a + // valid + // user + // defined + // method + this.scope + .problemReporter() + .duplicateMethodInType(this, methodDecl); + + methodDecl.binding = null; + // do not alter original method array until + // resolution is over, due to reentrance + // (143259) + if (resolvedMethods == this.methods) { + System + .arraycopy( + this.methods, + 0, + resolvedMethods = new MethodBinding[length], + 0, length); + } + resolvedMethods[i] = null; + failed++; + } + } + AbstractMethodDeclaration method2Decl = method2 + .sourceMethod(); + if (method2Decl != null && method2Decl.binding != null) { // ensure + // its + // a + // valid + // user + // defined + // method + this.scope.problemReporter().duplicateMethodInType( + this, method2Decl); + + method2Decl.binding = null; + // do not alter original method array until + // resolution is over, due to reentrance (143259) + if (resolvedMethods == this.methods) { + System + .arraycopy( + this.methods, + 0, + resolvedMethods = new MethodBinding[length], + 0, length); + } + resolvedMethods[j] = null; + failed++; + } } - - // duplicate method declarations found. - // discard the method that appears earlier in source. - // (it is always dead-code according to hoisting semantics of JavaScript) - - AbstractMethodDeclaration prevMethodDecl = prevMethod.sourceMethod(); - AbstractMethodDeclaration methodDecl = method.sourceMethod(); - - // do not alter original method array until - // resolution is over, due to reentrance - // (143259) - if (resolvedMethods == this.methods) { - System.arraycopy( - this.methods, - 0, - resolvedMethods = new MethodBinding[length], - 0, length); - } - - if (prevMethodDecl.sourceStart < methodDecl.sourceStart) { - this.scope.problemReporter().duplicateMethodInType(this, prevMethodDecl); - prevMethodDecl.binding = null; - resolvedMethods[prevIndex] = null; - - prevMethod = method; - prevIndex = i; - } else { - this.scope.problemReporter().duplicateMethodInType(this, methodDecl); - methodDecl.binding = null; + if (method.returnType == null && methodDecl == null) { // forget + // method + // with + // invalid + // return + // type... + // was + // kept + // to + // detect + // possible + // collisions + methodDecl = method.sourceMethod(); + if (methodDecl != null) { + methodDecl.binding = null; + } + // do not alter original method array until resolution + // is over, due to reentrance (143259) + if (resolvedMethods == this.methods) { + System + .arraycopy( + this.methods, + 0, + resolvedMethods = new MethodBinding[length], + 0, length); + } resolvedMethods[i] = null; + failed++; } - failed++; - } + } } finally { if (failed > 0) { int newSize = resolvedMethods.length - failed; -- 2.7.4