diff -r 106fa19e66ad cnd.completion/src/org/netbeans/modules/cnd/completion/csm/CsmProjectContentResolver.java --- a/cnd.completion/src/org/netbeans/modules/cnd/completion/csm/CsmProjectContentResolver.java Fri Jul 29 14:12:05 2016 +0300 +++ b/cnd.completion/src/org/netbeans/modules/cnd/completion/csm/CsmProjectContentResolver.java Tue Aug 02 17:57:01 2016 +0300 @@ -1344,7 +1344,7 @@ } } } - VisibilityInfo nextInfo = getNextInheritanceInfo(minVisibility, inherit, inheritanceLevel, friend); + VisibilityInfo nextInfo = getNextInheritanceInfo(contextDeclaration, minVisibility, inherit, inheritanceLevel, friend); CsmVisibility nextMinVisibility = nextInfo.visibility; int nextInheritanceLevel = nextInfo.inheritanceLevel; @@ -1392,7 +1392,7 @@ CsmClass baseClass = CsmInheritanceUtilities.getCsmClass(inherit); if (baseClass != null) { if (!baseClass.equals(csmClass)) { - VisibilityInfo nextInfo = getNextInheritanceInfo(minVisibility, inherit, inheritanceLevel, friend); + VisibilityInfo nextInfo = getNextInheritanceInfo(contextDeclaration, minVisibility, inherit, inheritanceLevel, friend); CsmVisibility nextMinVisibility = nextInfo.visibility; int nextInheritanceLevel = nextInfo.inheritanceLevel; if (nextMinVisibility != CsmVisibility.NONE) { @@ -1666,13 +1666,18 @@ return new VisibilityInfo(inheritanceLevel, minVisibility, friend); } - private VisibilityInfo getNextInheritanceInfo(CsmVisibility curMinVisibility, CsmInheritance inherit, int curInheritanceLevel, boolean friend) { + private VisibilityInfo getNextInheritanceInfo(CsmOffsetableDeclaration contextDeclaration, CsmVisibility curMinVisibility, CsmInheritance inherit, int curInheritanceLevel, boolean friend) { CsmVisibility nextMinVisibility; int nextInheritanceLevel = curInheritanceLevel; if (curInheritanceLevel == NO_INHERITANCE) { if(friend) { nextMinVisibility = CsmInheritanceUtilities.mergeInheritedVisibility(curMinVisibility, inherit.getVisibility()); nextInheritanceLevel = CHILD_INHERITANCE; + } else if (contextDeclaration == null && curMinVisibility == CsmInheritanceUtilities.MAX_VISIBILITY && inherit.getVisibility() == CsmVisibility.PUBLIC) { + // We are in global context => it may be a definition of inner member (which must be visible) + // so keep the MAX_VISIBILITY. Note, that this is a hack and different compilers have different behavior on that matter + nextMinVisibility = CsmInheritanceUtilities.MAX_VISIBILITY; + nextInheritanceLevel = NO_INHERITANCE; } else { nextMinVisibility = CsmInheritanceUtilities.mergeExtInheritedVisibility(curMinVisibility, inherit.getVisibility()); nextInheritanceLevel = NO_INHERITANCE; diff -r 106fa19e66ad cnd.completion/test/unit/data/org/netbeans/modules/cnd/completion/cplusplus/hyperlink/BasicHyperlinkTestCase/bug267382.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cnd.completion/test/unit/data/org/netbeans/modules/cnd/completion/cplusplus/hyperlink/BasicHyperlinkTestCase/bug267382.cpp Tue Aug 02 17:57:01 2016 +0300 @@ -0,0 +1,21 @@ +namespace bug267382 { + class Base267382 { + private: + class Inner267382 { + private: + static int y267382; + virtual void foo267382(); + }; + }; + + class Middle267382 : public Base267382 {}; + + class Derived267382 : public Middle267382 {}; + + int Derived267382::Inner267382::y267382 = 0; + + void Derived267382::Inner267382::foo267382() { + y267382 = 10; + return; + } +} \ No newline at end of file diff -r 106fa19e66ad cnd.completion/test/unit/src/org/netbeans/modules/cnd/completion/cplusplus/hyperlink/BasicHyperlinkTestCase.java --- a/cnd.completion/test/unit/src/org/netbeans/modules/cnd/completion/cplusplus/hyperlink/BasicHyperlinkTestCase.java Fri Jul 29 14:12:05 2016 +0300 +++ b/cnd.completion/test/unit/src/org/netbeans/modules/cnd/completion/cplusplus/hyperlink/BasicHyperlinkTestCase.java Tue Aug 02 17:57:01 2016 +0300 @@ -1236,6 +1236,13 @@ performTest("bug258511.cpp", 7, 10, "bug258511.cpp", 2, 3); } + public void testBug267382() throws Exception { + // Bug 267382 - Out of class function definition is not recognized under certain conditions + performTest("bug267382.cpp", 7, 29, "bug267382.cpp", 17, 5); + performTest("bug267382.cpp", 17, 41, "bug267382.cpp", 7, 13); + performTest("bug267382.cpp", 15, 40, "bug267382.cpp", 6, 13); + } + public static class Failed extends HyperlinkBaseTestCase { @Override diff -r 106fa19e66ad cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/FunctionImplEx.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/FunctionImplEx.java Fri Jul 29 14:12:05 2016 +0300 +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/FunctionImplEx.java Tue Aug 02 17:57:01 2016 +0300 @@ -46,6 +46,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -58,12 +59,17 @@ import org.netbeans.modules.cnd.api.model.CsmNamespace; import org.netbeans.modules.cnd.api.model.CsmNamespaceDefinition; import org.netbeans.modules.cnd.api.model.CsmObject; +import org.netbeans.modules.cnd.api.model.CsmOffsetable; import org.netbeans.modules.cnd.api.model.CsmOffsetableDeclaration; import org.netbeans.modules.cnd.api.model.CsmQualifiedNamedElement; import org.netbeans.modules.cnd.api.model.CsmScope; +import org.netbeans.modules.cnd.api.model.services.CsmExpressionResolver; import org.netbeans.modules.cnd.api.model.services.CsmSelect; import org.netbeans.modules.cnd.api.model.services.CsmSelect.CsmFilter; +import org.netbeans.modules.cnd.api.model.services.CsmSymbolResolver; +import org.netbeans.modules.cnd.api.model.util.CsmBaseUtilities; import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities; +import org.netbeans.modules.cnd.apt.utils.APTUtils; import org.netbeans.modules.cnd.modelimpl.content.file.FileContent; import org.netbeans.modules.cnd.modelimpl.csm.core.AstRenderer; import org.netbeans.modules.cnd.modelimpl.csm.core.AstUtil; @@ -160,8 +166,9 @@ CharSequence[] cnn = classOrNspNames; if( cnn != null && cnn.length > 0) { Resolver resolver = ResolverFactory.createResolver(this); + CsmObject obj = null; try { - CsmObject obj = resolver.resolve(cnn, Resolver.CLASSIFIER | Resolver.NAMESPACE); + obj = resolver.resolve(cnn, Resolver.CLASSIFIER | Resolver.NAMESPACE); if (CsmKindUtilities.isClassifier(obj)) { CsmClassifier cls = resolver.getOriginalClassifier((CsmClassifier)obj); if (cls != null) { @@ -176,6 +183,26 @@ } finally { ResolverFactory.releaseResolver(resolver); } + // 1) Check that resolver found nothing. It is unlikely that + // further resolving will return different object. + // 2) Check that length of qualified name is more than 1. + // Seems that it makes no sense to resolve qualified name + // with one element any further. + if (obj == null && cnn.length > 1) { + StringBuilder sb = new StringBuilder(cnn[0]); + for (int i = 1; i < cnn.length; ++i) { + sb.append(APTUtils.SCOPE).append(cnn[i]); + } + int startOffset = getStartOffset(); + Collection resolved = CsmExpressionResolver.resolveObjects(sb.toString(), getContainingFile(), startOffset, null); + if (resolved != null && !resolved.isEmpty()) { + for (CsmObject candidate : resolved) { + if (CsmKindUtilities.isClass(candidate) || CsmKindUtilities.isNamespace(candidate)) { + return candidate; + } + } + } + } } return null; } diff -r 106fa19e66ad cnd.modelimpl/test/unit/data/goldenfiles/org/netbeans/modules/cnd/modelimpl/trace/FileModelTest/resolver_ns_general.cc.dat --- a/cnd.modelimpl/test/unit/data/goldenfiles/org/netbeans/modules/cnd/modelimpl/trace/FileModelTest/resolver_ns_general.cc.dat Fri Jul 29 14:12:05 2016 +0300 +++ b/cnd.modelimpl/test/unit/data/goldenfiles/org/netbeans/modules/cnd/modelimpl/trace/FileModelTest/resolver_ns_general.cc.dat Tue Aug 02 17:57:01 2016 +0300 @@ -27,7 +27,7 @@ FIELD PRIVATE a [12:17/183-12:23/189] TYPE: int TEXT=int [12:17/183-12:20/186] INIT: null SCOPE: CCC FIELD PRIVATE static b [13:17/206-13:40/229] TYPE: const int TEXT=const int [13:17/206-13:33/222] INIT: text='5' SCOPE: CCC FUNCTION boo [14:25/254-14:35/264] MethodImpl SCOPE: CCC - DEFINITION: null + DEFINITION: boo [45:5/762-48:6/829] SIGNATURE boo() UNIQUE NAME F:rng::C::CC::CCC::boo() PARAMETERS: @@ -63,8 +63,8 @@ STATEMENT RETURN [42:9/741-42:18/750] SCOPE: Stmt [40:19/712-43:6/756] text: 'return a;' FUNCTION DEFINITION boo [45:5/762-48:6/829] FunctionDefinitionImpl SCOPE: resolver_ns_general.cc SIGNATURE boo() - UNIQUE NAME f:rng::CC::CCC::boo() - DECLARATION: null + UNIQUE NAME f:rng::C::CC::CCC::boo() + DECLARATION: boo [14:25/254-14:35/264] PARAMETERS: RETURNS int TEXT=int [45:5/762-45:8/765] STATEMENT COMPOUND [45:24/781-48:6/829] SCOPE: boo @@ -106,7 +106,7 @@ FIELD PRIVATE a [12:17/183-12:23/189] TYPE: int TEXT=int [12:17/183-12:20/186] INIT: null SCOPE: CCC FIELD PRIVATE static b [13:17/206-13:40/229] TYPE: const int TEXT=const int [13:17/206-13:33/222] INIT: text='5' SCOPE: CCC FUNCTION boo [14:25/254-14:35/264] MethodImpl SCOPE: CCC - DEFINITION: null + DEFINITION: boo [45:5/762-48:6/829] SIGNATURE boo() UNIQUE NAME F:rng::C::CC::CCC::boo() PARAMETERS: diff -r 106fa19e66ad cnd.modelimpl/test/unit/data/goldenfiles/org/netbeans/modules/cnd/modelimpl/trace/FileModelTest/resolver_ns_using_declaration.cc.dat --- a/cnd.modelimpl/test/unit/data/goldenfiles/org/netbeans/modules/cnd/modelimpl/trace/FileModelTest/resolver_ns_using_declaration.cc.dat Fri Jul 29 14:12:05 2016 +0300 +++ b/cnd.modelimpl/test/unit/data/goldenfiles/org/netbeans/modules/cnd/modelimpl/trace/FileModelTest/resolver_ns_using_declaration.cc.dat Tue Aug 02 17:57:01 2016 +0300 @@ -37,7 +37,7 @@ MEMBERS: FIELD PRIVATE static b [24:17/363-24:40/386] TYPE: const int TEXT=const int [24:17/363-24:33/379] INIT: text='5' SCOPE: CCC FUNCTION boo [25:25/411-25:35/421] MethodImpl SCOPE: CCC - DEFINITION: null + DEFINITION: boo [45:1/620-48:2/657] SIGNATURE boo() UNIQUE NAME F:rnud_2::C::CC::CCC::boo() PARAMETERS: @@ -62,8 +62,8 @@ USING NAMESPACE. ::rnud_2 [43:1/593-43:25/617]; REF NS: rnud_2 SCOPE: null FUNCTION DEFINITION boo [45:1/620-48:2/657] FunctionDefinitionImpl SCOPE: resolver_ns_using_declaration.cc SIGNATURE boo() - UNIQUE NAME f:CC::CCC::boo() - DECLARATION: null + UNIQUE NAME f:rnud_2::C::CC::CCC::boo() + DECLARATION: boo [25:25/411-25:35/421] PARAMETERS: RETURNS int TEXT=int [45:1/620-45:4/623] STATEMENT COMPOUND [45:20/639-48:2/657] SCOPE: boo @@ -146,7 +146,7 @@ MEMBERS: FIELD PRIVATE static b [24:17/363-24:40/386] TYPE: const int TEXT=const int [24:17/363-24:33/379] INIT: text='5' SCOPE: CCC FUNCTION boo [25:25/411-25:35/421] MethodImpl SCOPE: CCC - DEFINITION: null + DEFINITION: boo [45:1/620-48:2/657] SIGNATURE boo() UNIQUE NAME F:rnud_2::C::CC::CCC::boo() PARAMETERS: