diff --git a/cnd.api.model/src/org/netbeans/modules/cnd/api/model/services/CsmTypes.java b/cnd.api.model/src/org/netbeans/modules/cnd/api/model/services/CsmTypes.java --- a/cnd.api.model/src/org/netbeans/modules/cnd/api/model/services/CsmTypes.java +++ b/cnd.api.model/src/org/netbeans/modules/cnd/api/model/services/CsmTypes.java @@ -69,7 +69,7 @@ } public static CsmType createSimpleType(CsmClassifier cls, OffsetDescriptor offs) { - return getProvider().createType(cls, new TypeDescriptor(false, false, 0, 0), offs); + return getProvider().createType(cls, new TypeDescriptor(false, 0, 0, 0), offs); } /** @@ -78,7 +78,7 @@ * @return new type */ public static CsmType createConstType(CsmType orig) { - return getProvider().createType(orig, new TypeDescriptor(true, orig.isReference(), orig.getPointerDepth(), orig.getArrayDepth())); + return getProvider().createType(orig, new TypeDescriptor(true, TypeDescriptor.getReferenceType(orig), orig.getPointerDepth(), orig.getArrayDepth())); } /** @@ -95,7 +95,7 @@ } else { arrDepth = Math.max(arrDepth - 1, 0); } - return getProvider().createType(type, new TypeDescriptor(type.isConst(), type.isReference(), ptrDepth, arrDepth)); + return getProvider().createType(type, new TypeDescriptor(type.isConst(), TypeDescriptor.getReferenceType(type), ptrDepth, arrDepth)); } //@Immutable @@ -125,12 +125,33 @@ //@Immutable public static final class TypeDescriptor { + + public static final int NON_REFERENCE = 0; + + public static final int REFERENCE = 1; + + public static final int RVALUE_REFERENCE = 2; + + public static int getReferenceType(CsmType type) { + if (type.isRValueReference()) { + return RVALUE_REFERENCE; + } else if (type.isReference()) { + return REFERENCE; + } + return NON_REFERENCE; + } + + public static int getReferenceType(TypeDescriptor td) { + return td._reference; + } + + private final boolean _const; - private final boolean _reference; + private final int _reference; private final int _ptrDepth; private final int _arrDepth; - public TypeDescriptor(boolean _const, boolean _reference, int _ptrDepth, int _arrDepth) { + public TypeDescriptor(boolean _const, int _reference, int _ptrDepth, int _arrDepth) { this._const = _const; this._reference = _reference; this._ptrDepth = _ptrDepth; @@ -150,7 +171,11 @@ } public boolean isReference() { - return _reference; + return _reference > 0; + } + + public boolean isRValueReference() { + return _reference > 1; } } diff --git a/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CompletionSupport.java b/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CompletionSupport.java --- a/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CompletionSupport.java +++ b/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CompletionSupport.java @@ -65,15 +65,19 @@ import org.netbeans.cnd.api.lexer.CppTokenId; import org.netbeans.modules.cnd.api.model.CsmClass; import org.netbeans.modules.cnd.api.model.CsmClassifier; +import org.netbeans.modules.cnd.api.model.CsmConstructor; import org.netbeans.modules.cnd.api.model.CsmDeclaration; import org.netbeans.modules.cnd.api.model.CsmField; import org.netbeans.modules.cnd.api.model.CsmFile; import org.netbeans.modules.cnd.api.model.CsmFunction; import org.netbeans.modules.cnd.api.model.CsmFunctional; import org.netbeans.modules.cnd.api.model.CsmMember; +import org.netbeans.modules.cnd.api.model.CsmObject; import org.netbeans.modules.cnd.api.model.CsmOffsetableDeclaration; import org.netbeans.modules.cnd.api.model.CsmParameter; +import org.netbeans.modules.cnd.api.model.CsmSpecializationParameter; import org.netbeans.modules.cnd.api.model.CsmTemplate; +import org.netbeans.modules.cnd.api.model.CsmTemplateParameter; import org.netbeans.modules.cnd.api.model.CsmType; import org.netbeans.modules.cnd.api.model.CsmVariable; import org.netbeans.modules.cnd.api.model.deep.CsmReturnStatement; @@ -81,20 +85,27 @@ import org.netbeans.modules.cnd.api.model.deep.CsmStatement.Kind; import org.netbeans.modules.cnd.api.model.services.CsmClassifierResolver; import org.netbeans.modules.cnd.api.model.services.CsmInheritanceUtilities; +import org.netbeans.modules.cnd.api.model.services.CsmInstantiationProvider; import org.netbeans.modules.cnd.api.model.services.CsmMacroExpansion; +import org.netbeans.modules.cnd.api.model.services.CsmTypes; +import org.netbeans.modules.cnd.api.model.util.CsmBaseUtilities; import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities; import org.netbeans.modules.cnd.api.model.util.UIDs; import org.netbeans.modules.cnd.completion.cplusplus.CsmFinderFactory; +import org.netbeans.modules.cnd.completion.cplusplus.ext.CsmCompletionQuery.Context; import org.netbeans.modules.cnd.completion.csm.CompletionUtilities; import org.netbeans.modules.cnd.completion.csm.CsmContext; import org.netbeans.modules.cnd.completion.csm.CsmContextUtilities; import org.netbeans.modules.cnd.completion.csm.CsmOffsetResolver; import org.netbeans.modules.cnd.completion.csm.CsmOffsetUtilities; import org.netbeans.modules.cnd.completion.impl.xref.FileReferencesContext; +import org.netbeans.modules.cnd.modelutil.CsmUtilities; import org.netbeans.modules.editor.NbEditorUtilities; +import org.netbeans.spi.editor.completion.CompletionItem; import org.netbeans.spi.editor.completion.CompletionProvider; import org.openide.filesystems.FileObject; import org.openide.loaders.DataObject; +import org.openide.util.Pair; /** * @@ -378,15 +389,22 @@ /** Filter the list of the methods (usually returned from * Finder.findMethods()) or the list of the constructors * by the given parameter specification. + * @param ctx - completion context * @param methodList list of the methods. They should have the same * name but in fact they don't have to. + * @param exp - instantiation params * @param parmTypes parameter types specification. If set to null, no filtering * is performed and the same list is returned. If a particular * @param acceptMoreParameters useful for code completion to get * even the methods with more parameters. */ - public static Collection filterMethods(Collection methodList, List parmTypeList, - boolean acceptMoreParameters, boolean acceptIfSameNumberParams) { + static Collection filterMethods(Context ctx, + Collection methodList, + CsmCompletionExpression exp, + List parmTypeList, + boolean acceptMoreParameters, + boolean acceptIfSameNumberParams + ) { Collection result = filterMethods(methodList, parmTypeList, acceptMoreParameters, acceptIfSameNumberParams, false); if (result.size() > 1) { // it seems that this call couldn't filter anything @@ -394,7 +412,7 @@ // perform more accurate filtering if it is a strict request (for navigation probably) if (!acceptMoreParameters && acceptIfSameNumberParams) { - result = accurateFilterMethods(result, parmTypeList); + result = accurateFilterMethods(ctx, result, exp, parmTypeList); } } return result; @@ -490,12 +508,13 @@ * Please note: This method is designed to be called after preliminary filtering. * But this is not a necessary requirement. * + * @param ctx - completion context * @param methods * @param paramTypes * * @return candidates */ - private static Collection accurateFilterMethods(Collection methods, List paramTypes) { + private static Collection accurateFilterMethods(Context ctx, Collection methods, CsmCompletionExpression exp, List paramTypes) { if (methods.size() <= 1) { return methods; } @@ -551,8 +570,20 @@ break; } } - prev = candidate; - result.add(candidate.function); + + boolean validCandidate = true; + + if (CsmKindUtilities.isTemplate(candidate.function)) { + // we should check if this function is viable + CsmType retType = extractFunctionType(ctx, Arrays.asList(candidate.function), exp, paramTypes); + CsmClassifier cls = retType != null ? CsmBaseUtilities.getClassifier(retType, ctx.getContextFile(), ctx.getEndOffset(), true) : null; + validCandidate = (cls != null && cls.isValid()); + } + + if (validCandidate) { + prev = candidate; + result.add(candidate.function); + } } return result.isEmpty() ? methods : result; @@ -906,6 +937,335 @@ } return false; } + + static CsmType extractFunctionType(Context context, Collection mtdList, CsmCompletionExpression genericNameExp, List typeList) { + CsmType out = null; + if (mtdList.isEmpty()) { + return null; + } + for (CsmFunctional fun : mtdList) { + CsmObject entity = fun; + + if (CsmKindUtilities.isConstructor(entity)) { + entity = ((CsmConstructor) entity).getContainingClass(); + } + + if (CsmKindUtilities.isTemplate(entity)) { + CsmObject inst = createInstantiation(context, (CsmTemplate) entity, genericNameExp, typeList); + if (CsmKindUtilities.isFunction(inst) || CsmKindUtilities.isClassifier(inst)) { + entity = inst; + } + } + + if (CsmKindUtilities.isFunctional(entity)) { + out = ((CsmFunctional) entity).getReturnType(); + } else if (CsmKindUtilities.isClassifier(entity)) { + out = CsmCompletion.createType((CsmClassifier) entity, 0, 0, 0, false); + } + if (out != null) { + break; + } + } + return out; + } + + static CsmObject createInstantiation(Context context, CsmTemplate template, CsmCompletionExpression exp, List typeList) { + if (exp != null || !typeList.isEmpty()) { + CsmInstantiationProvider ip = CsmInstantiationProvider.getDefault(); + List params = new ArrayList(); + params.addAll(collectInstantiationParameters(context, ip, exp)); + if (CsmKindUtilities.isFunction(template)) { + params.addAll(collectInstantiationParameters(ip, (CsmFunction)template, params.size(), typeList)); + } + if (!params.isEmpty()) { + return ip.instantiate(template, params); + } + } + return null; + } + + static List collectInstantiationParameters(Context context, CsmInstantiationProvider ip, CsmCompletionExpression exp) { + if (exp != null) { + List params = new ArrayList(); + if (exp.getExpID() == CsmCompletionExpression.GENERIC_TYPE) { + int paramsNumber = exp.getParameterCount() - 1; + for (int i = 0; i < paramsNumber; i++) { + CsmCompletionExpression paramInst = exp.getParameter(i + 1); + if (paramInst != null) { + switch (paramInst.getExpID()) { + case CsmCompletionExpression.CONSTANT: + params.add(ip.createExpressionBasedSpecializationParameter(paramInst.getTokenText(0), + context.getContextFile(), paramInst.getTokenOffset(0), paramInst.getTokenOffset(0) + paramInst.getTokenLength(0))); + break; + default: + CsmType type = null; + + if (!isExpression(paramInst)) { + type = context.resolveType(paramInst); + if (type != null) { + List candidates = context.resolveNextExp(paramInst); + if (candidates != null && (candidates.get(0) instanceof CsmResultItem.VariableResultItem)) { + type = null; + } + } + } + + if (type != null) { + params.add(ip.createTypeBasedSpecializationParameter(type)); + } else { + RenderedExpression renderedExpression = renderExpression(paramInst); + params.add(ip.createExpressionBasedSpecializationParameter( + renderedExpression.text, + context.getContextFile(), + renderedExpression.startOffset, + renderedExpression.endOffset + )); + } + } + } else { + break; + } + } + } + return params; + } + return Collections.emptyList(); + } + + static List collectInstantiationParameters(CsmInstantiationProvider ip, CsmFunction function, int explicitelyMappedSize, List typeList) { + if (CsmKindUtilities.isTemplate(function)) { + List result = new ArrayList(); + + CsmTemplate template = (CsmTemplate) function; + List templateParams = template.getTemplateParameters(); + + if (templateParams.size() > explicitelyMappedSize) { + Map paramsMap = gatherTemplateParamsMap(function, typeList); + + for (int i = explicitelyMappedSize; i < templateParams.size(); i++) { + CsmTemplateParameter param = templateParams.get(i); + CsmType mappedType = paramsMap.get(param); + if (mappedType != null) { + result.add(ip.createTypeBasedSpecializationParameter(mappedType)); + } else { + // error + return result; + } + } + } + + return result; + } + return Collections.emptyList(); + } + + static Map gatherTemplateParamsMap(CsmFunction function, List typeList) { + assert CsmKindUtilities.isTemplate(function) : "Attempt to gather template parameters map from non-template function"; // NOI18N + CsmTemplate template = (CsmTemplate) function; + + Map map = new HashMap(); + + for (CsmTemplateParameter templateParam : template.getTemplateParameters()) { + int paramIndex = 0; + for (CsmParameter param : function.getParameters()) { + if (paramIndex >= typeList.size()) { + break; + } + CsmType paramType = param.getType(); + CsmType calculatedType = calcTypeFromParameter(templateParam, paramType, typeList.get(paramIndex)); + if (calculatedType != null) { + map.put(templateParam, calculatedType); + } + paramIndex++; + } + } + + return map; + } + + static CsmType calcTypeFromParameter(CsmTemplateParameter templateParam, CsmType paramType, CsmType passedType) { + if (paramType != null) { + CsmClassifier cls = paramType.getClassifier(); + if (cls != null && cls.getQualifiedName().toString().equals(templateParam.getQualifiedName().toString())) { + boolean hasChanges = false; + + boolean newConst = false; + int newReference = CsmTypes.TypeDescriptor.NON_REFERENCE; + int newPtrDepth = 0; + int newArrayDepth = 0; + + CsmType underlyingType = CsmUtilities.iterateTypeChain(passedType, new CsmUtilities.ConstantPredicate(false)); + + if (paramType.isConst()) { + if (underlyingType.isConst()) { + hasChanges = true; + newConst = false; + } else { + return null; + } + } + + if (paramType.isPointer()) { + if (paramType.getPointerDepth() <= underlyingType.getPointerDepth()) { + hasChanges = true; + newPtrDepth = underlyingType.getPointerDepth() - paramType.getPointerDepth(); + } else { + return null; + } + } + + if (paramType.isReference()) { + if (underlyingType.isReference()) { + hasChanges = true; + newReference = CsmTypes.TypeDescriptor.NON_REFERENCE; + } else { + return null; + } + } + + if (paramType.isRValueReference()) { + if (underlyingType.isRValueReference()) { + hasChanges = true; + newReference = CsmTypes.TypeDescriptor.NON_REFERENCE; + } else { + return null; + } + } + + if (hasChanges) { + CsmTypes.TypeDescriptor td = new CsmTypes.TypeDescriptor( + newConst, + newReference, + newPtrDepth, + newArrayDepth + ); + + return CsmTypes.createType(underlyingType, td); + } + + return passedType; + } + } + return null; + } + + static RenderedExpression renderExpression(CsmCompletionExpression expr) { + if (expr == null) { + return null; + } + switch (expr.getExpID()) { + case CsmCompletionExpression.GENERIC_TYPE: { + StringBuilder sb = new StringBuilder(); + int startExpOffset = expr.getTokenOffset(0); + int endExpOffset = startExpOffset; + + for (int paramIndex = 0; paramIndex < expr.getParameterCount(); paramIndex++) { + RenderedExpression current = renderExpression(expr.getParameter(paramIndex)); + + sb.append(current.text); + + if (paramIndex > 0) { + if (paramIndex < expr.getParameterCount() - 1) { + sb.append(","); // NOI18N + } else { + sb.append(">"); // NOI18N + } + endExpOffset++; + } else { + sb.append(expr.getTokenText(0)); + } + + endExpOffset = current.endOffset; + } + + return new RenderedExpression(sb.toString(), startExpOffset, endExpOffset); + } + + case CsmCompletionExpression.UNARY_OPERATOR: + case CsmCompletionExpression.OPERATOR: + case CsmCompletionExpression.SCOPE: { + StringBuilder sb = new StringBuilder(); + int startExpOffset = -1; + int endExprOffset = -1; + + int paramCount = expr.getParameterCount(); + int tokenCount = expr.getTokenCount(); + int paramIndex = 0; + int tokenIndex = 0; + + RenderedExpression renderedParam = null; + RenderedExpression renderedToken = null; + boolean lastWasParam = false; + boolean lastWasToken = false; + + boolean entityChanged = true; + + while (entityChanged) { + entityChanged = false; + + if (renderedParam == null && paramIndex < paramCount) { + renderedParam = renderExpression(expr.getParameter(paramIndex)); + paramIndex++; + } + + if (renderedToken == null && tokenIndex < tokenCount) { + renderedToken = new RenderedExpression( + expr.getTokenText(tokenIndex).toString(), + expr.getTokenOffset(tokenIndex), + expr.getTokenOffset(tokenIndex) + expr.getTokenLength(tokenIndex) + ); + tokenIndex++; + } + + RenderedExpression chosenExpression; + + if (renderedParam != null && renderedToken != null) { + if (renderedParam.startOffset < renderedToken.startOffset) { + chosenExpression = renderedParam; + } else { + chosenExpression = renderedToken; + } + } else if (renderedToken == null) { + chosenExpression = renderedParam; + } else { + chosenExpression = renderedToken; + } + + if (chosenExpression != null) { + if (chosenExpression == renderedParam) { + renderedParam = null; + entityChanged = !lastWasParam; + lastWasParam = true; + lastWasToken = false; + } else { + renderedToken = null; + entityChanged = !lastWasToken; + lastWasToken = true; + lastWasParam = false; + } + + if (entityChanged) { + sb.append(chosenExpression.text); + if (startExpOffset == -1) { + startExpOffset = chosenExpression.startOffset; + } + endExprOffset = chosenExpression.endOffset; + } + } + } + + return new RenderedExpression(sb.toString(), startExpOffset, endExprOffset); + } + + default: { + return new RenderedExpression( + expr.getTokenText(0), + expr.getTokenOffset(0), + expr.getTokenOffset(0) + expr.getTokenLength(0) + ); + } + } + } CsmType findExactVarType(CsmFile file, String var, int docPos, FileReferencesContext refContext) { if (file == null) { @@ -1001,7 +1361,12 @@ } } return null; - } + } + + private static boolean isExpression(CsmCompletionExpression expression) { + return expression.getExpID() == CsmCompletionExpression.OPERATOR || + expression.getExpID() == CsmCompletionExpression.UNARY_OPERATOR; + } private int findLCurlsNumberBeforPosition(String s, int pos) { int cursor = -1; @@ -1075,4 +1440,25 @@ public void changedUpdate(DocumentEvent e) { this.lastSeparatorOffset = -1; } + + + static class RenderedExpression { + + public final String text; + + public final int startOffset; + + public final int endOffset; + + public RenderedExpression(String text, int startOffset, int endOffset) { + this.text = text; + this.startOffset = startOffset; + this.endOffset = endOffset; + } + + @Override + public String toString() { + return text + "[" + startOffset + "," + endOffset + "]"; // NOI18N + } + } } diff --git a/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CsmCompletionQuery.java b/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CsmCompletionQuery.java --- a/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CsmCompletionQuery.java +++ b/cnd.completion/src/org/netbeans/modules/cnd/completion/cplusplus/ext/CsmCompletionQuery.java @@ -84,8 +84,8 @@ import org.netbeans.modules.cnd.api.model.CsmField; import org.netbeans.modules.cnd.api.model.CsmFile; import org.netbeans.modules.cnd.api.model.CsmFunction; +import org.netbeans.modules.cnd.api.model.CsmFunctionPointerClassifier; import org.netbeans.modules.cnd.api.model.CsmFunctionPointerType; -import org.netbeans.modules.cnd.api.model.CsmFunctionPointerClassifier; import org.netbeans.modules.cnd.api.model.CsmFunctional; import org.netbeans.modules.cnd.api.model.CsmInheritance; import org.netbeans.modules.cnd.api.model.CsmInstantiation; @@ -122,6 +122,7 @@ 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.CsmSelect.CsmFilterBuilder; +import org.netbeans.modules.cnd.api.model.services.CsmTypes; import org.netbeans.modules.cnd.api.model.util.CsmBaseUtilities; import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities; import org.netbeans.modules.cnd.api.model.util.CsmSortUtilities; @@ -141,6 +142,7 @@ import org.netbeans.spi.editor.completion.CompletionItem; import org.openide.text.CloneableEditorSupport; import org.openide.util.NbBundle; +import org.openide.util.Pair; /** * @@ -1145,6 +1147,14 @@ this.instantiateTypes = instantiateTypes; this.instantiations = instantiations; } + + CsmFile getContextFile() { + return contextFile; + } + + int getEndOffset() { + return endOffset; + } private int convertOffset(int pos) { return sup.doc2context(pos); @@ -1398,37 +1408,6 @@ return out; } - private CsmType extractFunctionType(Collection mtdList, CsmCompletionExpression genericNameExp, List typeList) { - CsmType out = null; - if (mtdList.isEmpty()) { - return null; - } - for (CsmFunctional fun : mtdList) { - CsmObject entity = fun; - - if (CsmKindUtilities.isConstructor(entity)) { - entity = ((CsmConstructor) entity).getContainingClass(); - } - - if (CsmKindUtilities.isTemplate(entity)) { - CsmObject inst = createInstantiation((CsmTemplate) entity, genericNameExp, typeList); - if (CsmKindUtilities.isFunction(inst) || CsmKindUtilities.isClassifier(inst)) { - entity = inst; - } - } - - if (CsmKindUtilities.isFunctional(entity)) { - out = ((CsmFunctional) entity).getReturnType(); - } else if (CsmKindUtilities.isClassifier(entity)) { - out = CsmCompletion.createType((CsmClassifier) entity, 0, 0, 0, false); - } - if (out != null) { - break; - } - } - return out; - } - /*private CsmClassifier resolveTemplateParameter(CsmClassifier cls, CsmType type) { if (cls instanceof CsmClassifierBasedTemplateParameter) { CsmClassifierBasedTemplateParameter tp = (CsmClassifierBasedTemplateParameter) cls; @@ -1450,7 +1429,7 @@ } return cls; }*/ - private CsmType resolveType(CsmCompletionExpression exp) { + CsmType resolveType(CsmCompletionExpression exp) { CsmType typ = exp.getCachedType(); if (typ == null) { Context ctx = (Context) clone(); @@ -1465,11 +1444,29 @@ exp.cacheType(typ); // restore old ctx.compResolver.setResolveScope(old); - } + } } return typ; } + List resolveNextExp(CsmCompletionExpression exp) { + Context ctx = (Context) clone(); + ctx.setFindType(false); + // when resolve type use full scope of search + QueryScope old = ctx.compResolver.setResolveScope(QueryScope.GLOBAL_QUERY); + try { + if (ctx.resolveExp(exp, true)) { + if (ctx.result != null && !ctx.result.getItems().isEmpty()) { + return ctx.result.getItems(); + } + } + } finally { + // restore old + ctx.compResolver.setResolveScope(old); + } + return null; + } + private boolean isProjectBeeingParsed() { return CsmCompletionQuery.this.isProjectBeeingParsed(openingSource); } @@ -2066,7 +2063,7 @@ lastType = typ; CsmClassifier cls = getClassifier(lastType, contextFile, endOffset); if (cls != null && CsmKindUtilities.isTemplate(cls)) { - CsmObject obj = createInstantiation((CsmTemplate)cls, item, Collections.emptyList()); + CsmObject obj = CompletionSupport.createInstantiation(this, (CsmTemplate)cls, item, Collections.emptyList()); if (obj != null && CsmKindUtilities.isClass(obj)) { lastType = CsmCompletion.createType((CsmClass)obj, 0, 0, 0, false); } @@ -2158,10 +2155,10 @@ if (!mtdList.isEmpty()) { List typeList = getTypeList(item, 0); // check exact overloaded operator - Collection filtered = CompletionSupport.filterMethods(mtdList, typeList, false, false); + Collection filtered = CompletionSupport.filterMethods(this, mtdList, null, typeList, false, false); if (filtered.size() > 0) { mtdList = filtered; - lastType = extractFunctionType(mtdList, null, typeList); + lastType = CompletionSupport.extractFunctionType(this, mtdList, null, typeList); } else if (item.getParameterCount() > 1) { CsmType type0 = resolveType(item.getParameter(0)); CsmType type1 = resolveType(item.getParameter(1)); @@ -2672,7 +2669,7 @@ } if (cls != null) { if (CsmKindUtilities.isTemplate(cls) && genericNameExp != null) { - CsmObject inst = createInstantiation((CsmTemplate)cls, genericNameExp, Collections.emptyList()); + CsmObject inst = CompletionSupport.createInstantiation(this, (CsmTemplate)cls, genericNameExp, Collections.emptyList()); if (CsmKindUtilities.isClassifier(inst)) { cls = (CsmClassifier) inst; } @@ -2690,7 +2687,7 @@ } String parmStr = "*"; // NOI18N List typeList = getTypeList(item, 1); - Collection filtered = CompletionSupport.filterMethods(mtdList, typeList, methodOpen, true); + Collection filtered = CompletionSupport.filterMethods(this, mtdList, genericNameExp, typeList, methodOpen, true); if (filtered.size() > 0) { mtdList = filtered; parmStr = formatTypeList(typeList, methodOpen); @@ -2701,7 +2698,7 @@ formatType(lastType, true, true, false) + mtdName + '(' + parmStr + ')', item, endOffset, 0, 0, isProjectBeeingParsed(), contextElement, instantiateTypes); } else { - lastType = extractFunctionType(mtdList, genericNameExp, typeList); + lastType = CompletionSupport.extractFunctionType(this, mtdList, genericNameExp, typeList); staticOnly = false; } } else { @@ -2833,222 +2830,6 @@ } return false; } - - private CsmObject createInstantiation(CsmTemplate template, CsmCompletionExpression exp, List typeList) { - if (exp != null || !typeList.isEmpty()) { - CsmInstantiationProvider ip = CsmInstantiationProvider.getDefault(); - List params = new ArrayList(); - params.addAll(collectInstantiationParameters(ip, exp)); - if (CsmKindUtilities.isFunction(template)) { - params.addAll(collectInstantiationParameters(ip, (CsmFunction)template, params.size(), typeList)); - } - if (!params.isEmpty()) { - return ip.instantiate(template, params); - } - } - return null; - } - - private List collectInstantiationParameters(CsmInstantiationProvider ip, CsmCompletionExpression exp) { - if (exp != null) { - List params = new ArrayList(); - if (exp.getExpID() == CsmCompletionExpression.GENERIC_TYPE) { - int paramsNumber = exp.getParameterCount() - 1; - for (int i = 0; i < paramsNumber; i++) { - CsmCompletionExpression paramInst = exp.getParameter(i + 1); - if (paramInst != null) { - switch (paramInst.getExpID()) { - case CsmCompletionExpression.CONSTANT: - params.add(ip.createExpressionBasedSpecializationParameter(paramInst.getTokenText(0), - contextFile, paramInst.getTokenOffset(0), paramInst.getTokenOffset(0) + paramInst.getTokenLength(0))); - break; - default: - CsmType type = resolveType(paramInst); - if (type != null) { - params.add(ip.createTypeBasedSpecializationParameter(type)); - } else { - RenderedExpression renderedExpression = renderExpression(paramInst); - params.add(ip.createExpressionBasedSpecializationParameter( - renderedExpression.text, - contextFile, - renderedExpression.startOffset, - renderedExpression.endOffset - )); - } - } - } else { - break; - } - } - } - return params; - } - return Collections.emptyList(); - } - - private List collectInstantiationParameters(CsmInstantiationProvider ip, CsmFunction function, int explicitelyMappedSize, List typeList) { - if (CsmKindUtilities.isTemplate(function)) { - List result = new ArrayList(); - - CsmTemplate template = (CsmTemplate) function; - List templateParams = template.getTemplateParameters(); - - if (templateParams.size() > explicitelyMappedSize) { - Map paramsMap = gatherTemplateParamsMap(function, typeList); - - for (int i = explicitelyMappedSize; i < templateParams.size(); i++) { - CsmTemplateParameter param = templateParams.get(i); - CsmType mappedType = paramsMap.get(param); - if (mappedType != null) { - result.add(ip.createTypeBasedSpecializationParameter(mappedType)); - } else { - // error - return result; - } - } - } - - return result; - } - return Collections.emptyList(); - } - - private Map gatherTemplateParamsMap(CsmFunction function, List typeList) { - assert CsmKindUtilities.isTemplate(function) : "Attempt to gather template parameters map from non-template function"; // NOI18N - CsmTemplate template = (CsmTemplate) function; - - Map map = new HashMap(); - - for (CsmTemplateParameter templateParam : template.getTemplateParameters()) { - int paramIndex = 0; - for (CsmParameter param : function.getParameters()) { - if (paramIndex >= typeList.size()) { - break; - } - CsmType paramType = param.getType(); - if (paramType != null) { - CsmClassifier cls = paramType.getClassifier(); - if (cls != null) { - if (cls.getQualifiedName().toString().equals(templateParam.getQualifiedName().toString())) { - map.put(templateParam, typeList.get(paramIndex)); - } - } - } - paramIndex++; - } - } - - return map; - } - - private RenderedExpression renderExpression(CsmCompletionExpression expr) { - if (expr == null) { - return null; - } - switch (expr.getExpID()) { - case CsmCompletionExpression.SCOPE: { - StringBuilder sb = new StringBuilder(); - int startExpOffset = -1; - int endExprOffset = -1; - - int paramCount = expr.getParameterCount(); - int tokenCount = expr.getTokenCount(); - int paramIndex = 0; - int tokenIndex = 0; - - RenderedExpression renderedParam = null; - RenderedExpression renderedToken = null; - boolean lastWasParam = false; - boolean lastWasToken = false; - - boolean entityChanged = true; - - while (entityChanged) { - entityChanged = false; - - if (renderedParam == null && paramIndex < paramCount) { - renderedParam = renderExpression(expr.getParameter(paramIndex)); - paramIndex++; - } - - if (renderedToken == null && tokenIndex < tokenCount) { - renderedToken = new RenderedExpression( - expr.getTokenText(tokenIndex).toString(), - expr.getTokenOffset(tokenIndex), - expr.getTokenOffset(tokenIndex) + expr.getTokenLength(tokenIndex) - ); - tokenIndex++; - } - - RenderedExpression chosenExpression; - - if (renderedParam != null && renderedToken != null) { - if (renderedParam.startOffset < renderedToken.startOffset) { - chosenExpression = renderedParam; - } else { - chosenExpression = renderedToken; - } - } else if (renderedToken == null) { - chosenExpression = renderedParam; - } else { - chosenExpression = renderedToken; - } - - if (chosenExpression != null) { - if (chosenExpression == renderedParam) { - renderedParam = null; - entityChanged = !lastWasParam; - lastWasParam = true; - lastWasToken = false; - } else { - renderedToken = null; - entityChanged = !lastWasToken; - lastWasToken = true; - lastWasParam = false; - } - - if (entityChanged) { - sb.append(chosenExpression.text); - if (startExpOffset == -1) { - startExpOffset = chosenExpression.startOffset; - } - endExprOffset = chosenExpression.endOffset; - } - } - } - - return new RenderedExpression(sb.toString(), startExpOffset, endExprOffset); - } - - default: { - return new RenderedExpression( - expr.getTokenText(0), - expr.getTokenOffset(0), - expr.getTokenOffset(0) + expr.getTokenLength(0) - ); - } - } - } - - private class RenderedExpression { - - public final String text; - - public final int startOffset; - - public final int endOffset; - - public RenderedExpression(String text, int startOffset, int endOffset) { - this.text = text; - this.startOffset = startOffset; - this.endOffset = endOffset; - } - - @Override - public String toString() { - return text + "[" + startOffset + "," + endOffset + "]"; // NOI18N - } - } private CsmType findBuiltInFunctionReturnType(String mtdName, int tokenOffset) { CsmType out = null; diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/Instantiation.java b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/Instantiation.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/Instantiation.java +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/Instantiation.java @@ -1227,18 +1227,36 @@ } return new Type(type, instantiation); } - + + public static CsmType createType(CsmType type, List instantiations) { + for (CsmInstantiation instantiation : instantiations) { + type = createType(type, instantiation); + } + return type; + } + +// public static CsmType resolveTemplateParameterType(CsmType type, Map mapping) { +// if (CsmKindUtilities.isTemplateParameterType(type)) { +// LOG.log(Level.FINE, "Instantiation.resolveTemplateParameter {0}; mapping={1}\n", new Object[]{type.getText(), instantiation.getTemplateDeclaration().getName()}); +// CsmType resolvedType = resolveTemplateParameterType(((CsmTemplateParameterType) type).getParameter(), new MapHierarchy<>(mapping)); +// if (resolvedType != null) { +// return resolvedType; +// } +// } +// return type; +// } + public static CsmType resolveTemplateParameterType(CsmType type, CsmInstantiation instantiation) { if (CsmKindUtilities.isTemplateParameterType(type)) { LOG.log(Level.FINE, "Instantiation.resolveTemplateParameter {0}; mapping={1}\n", new Object[]{type.getText(), instantiation.getTemplateDeclaration().getName()}); - MapHierarchy mapping = TemplateUtils.gatherMapping(instantiation); + MapHierarchy mapping = new MapHierarchy<>(instantiation.getMapping()); CsmType resolvedType = resolveTemplateParameterType(((CsmTemplateParameterType) type).getParameter(), mapping); if (resolvedType != null) { return resolvedType; } } return type; - } + } public static CsmType resolveTemplateParameterType(CsmTemplateParameter templateParameter, Map mapping) { return resolveTemplateParameterType(templateParameter, new MapHierarchy<>(mapping)); diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/NestedType.java b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/NestedType.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/NestedType.java +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/NestedType.java @@ -132,11 +132,11 @@ classifier = getNestedClassifier(memberResolver, parentClassifier, getOwnText()); } } - if (!CsmBaseUtilities.isValid(classifier)) { - // try to resolve qualified name, not through the parent classifier - List fqn = getFullQName(); - classifier = renderClassifier(fqn.toArray(new CharSequence[fqn.size()])); - } +// if (!CsmBaseUtilities.isValid(classifier)) { +// // try to resolve qualified name, not through the parent classifier +// List fqn = getFullQName(); +// classifier = renderClassifier(fqn.toArray(new CharSequence[fqn.size()])); +// } _setClassifier(classifier); } if (isInstantiation() && CsmKindUtilities.isTemplate(classifier) && !((CsmTemplate)classifier).getTemplateParameters().isEmpty()) { diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/TypeImpl.java b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/TypeImpl.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/TypeImpl.java +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/csm/TypeImpl.java @@ -981,6 +981,10 @@ protected CsmClassifier _getClassifier() { CsmClassifier classifier = null; + boolean clearClassifier = false; + if (clearClassifier) { + classifierUID = null; + } if (classifierUID != null) { classifier = UIDCsmConverter.UIDtoDeclaration(classifierUID); } else { diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/ExpressionEvaluator.java b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/ExpressionEvaluator.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/ExpressionEvaluator.java +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/ExpressionEvaluator.java @@ -212,12 +212,12 @@ for (CsmTemplateParameter param : orderedParamsList) { Map newMapping = new HashMap(); CsmSpecializationParameter spec = inst.getMapping().get(param); - if(CsmKindUtilities.isExpressionBasedSpecalizationParameter(spec)) { + /*if(CsmKindUtilities.isExpressionBasedSpecalizationParameter(spec)) { Object o = eval(((CsmExpressionBasedSpecializationParameter) spec).getText().toString(), inst.getTemplateDeclaration(), mapHierarchy); CsmSpecializationParameter newSpec = ExpressionBasedSpecializationParameterImpl.create(o.toString(), spec.getContainingFile(), spec.getStartOffset(), spec.getEndOffset()); newMapping.put(param, newSpec); - } else { + } else*/ { newMapping.put(param, spec); } mapping.putAll(newMapping); diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/InstantiationProviderImpl.java b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/InstantiationProviderImpl.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/InstantiationProviderImpl.java +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/InstantiationProviderImpl.java @@ -120,6 +120,7 @@ import org.netbeans.modules.cnd.modelutil.CsmUtilities; import org.netbeans.modules.cnd.spi.model.services.CsmExpressionEvaluatorProvider; import org.netbeans.modules.cnd.utils.CndCollectionUtils; +import org.openide.util.Pair; /** * Service that provides template instantiations @@ -211,7 +212,7 @@ public CsmObject instantiate(CsmTemplate template, CsmInstantiation instantiation) { return instantiate(template, instantiation, true); } - + public CsmObject instantiate(CsmTemplate template, CsmInstantiation instantiation, boolean specialize) { return instantiate(template, null, 0, instantiation, specialize); } @@ -483,7 +484,7 @@ } private CsmClassifier specialize(CsmClassifier classifier, CsmFile contextFile, int contextOffset) { - List params = getInstantiationParams(classifier); + List>> params = getInstantiationParams(classifier); CsmClassifier specialization = null; if (CsmKindUtilities.isTemplate(classifier)) { List templateParams = ((CsmTemplate) classifier).getTemplateParameters(); @@ -493,7 +494,7 @@ // try to find full specialization of class CsmClass cls = (CsmClass) classifier; StringBuilder fqn = new StringBuilder(cls.getUniqueName()); - fqn.append(Instantiation.getInstantiationCanonicalText(params)); + fqn.append(Instantiation.getInstantiationCanonicalText(getPlainParams(params))); for (CsmProject proj : projects) { CsmDeclaration decl = proj.findDeclaration(fqn.toString()); @@ -651,20 +652,23 @@ return projects; } - private static CsmClassifier findBestSpecialization(Collection specializations, List params, final CsmClassifier cls) { + private static CsmClassifier findBestSpecialization(Collection specializations, List>> params, final CsmClassifier cls) { // TODO : update CsmClassifier bestSpecialization = null; boolean variadic = false; - List params2 = new ArrayList(); - for (CsmSpecializationParameter param : params) { + List>> params2 = new ArrayList>>(); + for (Pair> pair : params) { + CsmSpecializationParameter param = pair.first(); if(CsmKindUtilities.isVariadicSpecalizationParameter(param)) { - params2.addAll(((CsmVariadicSpecializationParameter)param).getArgs()); + for (CsmSpecializationParameter arg : ((CsmVariadicSpecializationParameter)param).getArgs()) { + params2.add(Pair.of(arg, pair.second())); + } variadic = true; } else { - params2.add(param); + params2.add(pair); } } params = params2; @@ -672,7 +676,8 @@ if (!specializations.isEmpty()) { int bestMatch = 0; int paramsSize = 0; - for (CsmSpecializationParameter param : params) { + for (Pair> pair : params) { + CsmSpecializationParameter param = pair.first(); if(CsmKindUtilities.isVariadicSpecalizationParameter(param)) { paramsSize += ((CsmVariadicSpecializationParameter)param).getArgs().size(); } else { @@ -682,48 +687,50 @@ List paramsText = new ArrayList(); List paramsType = new ArrayList(); - for (CsmSpecializationParameter param : params) { + for (Pair> pair : params) { + CsmSpecializationParameter param = pair.first(); if (CsmKindUtilities.isTypeBasedSpecalizationParameter(param)) { CsmType paramType = ((CsmTypeBasedSpecializationParameter) param).getType(); if (CsmKindUtilities.isInstantiation(cls)) { - // Try to instantiate type with appropriate instantiations - Iterator instIters = new Iterator() { - - private CsmInstantiation instantiation = (CsmInstantiation) cls; - - @Override - public boolean hasNext() { - return instantiation != null; - } - - @Override - public Object next() { - CsmInstantiation res = instantiation; - if (CsmKindUtilities.isInstantiation(instantiation.getTemplateDeclaration())) { - instantiation = (CsmInstantiation) instantiation.getTemplateDeclaration(); - } else { - instantiation = null; - } - return res; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Not supported."); // NOI18N - } - }; - - CsmType instantiatedType = createTypeInstantiationForTypeParameter((CsmTypeBasedSpecializationParameter) param, instIters, 0); -// CsmType instantiatedType = null; - - if (instantiatedType != null) { - // If success then it will be parameter type - paramType = instantiatedType; - } else { - // If instantiation failed then create instantiation with the the full class isntantiation - paramType = Instantiation.createType(paramType, (CsmInstantiation) cls); - } + paramType = Instantiation.createType(paramType, pair.second()); +// // Try to instantiate type with appropriate instantiations +// Iterator instIters = new Iterator() { +// +// private CsmInstantiation instantiation = (CsmInstantiation) cls; +// +// @Override +// public boolean hasNext() { +// return instantiation != null; +// } +// +// @Override +// public Object next() { +// CsmInstantiation res = instantiation; +// if (CsmKindUtilities.isInstantiation(instantiation.getTemplateDeclaration())) { +// instantiation = (CsmInstantiation) instantiation.getTemplateDeclaration(); +// } else { +// instantiation = null; +// } +// return res; +// } +// +// @Override +// public void remove() { +// throw new UnsupportedOperationException("Not supported."); // NOI18N +// } +// }; +// +// CsmType instantiatedType = createTypeInstantiationForTypeParameter((CsmTypeBasedSpecializationParameter) param, instIters, 0); +//// CsmType instantiatedType = null; +// +// if (instantiatedType != null) { +// // If success then it will be parameter type +// paramType = instantiatedType; +// } else { +// // If instantiation failed then create instantiation with the the full class isntantiation +// paramType = Instantiation.createType(paramType, (CsmInstantiation) cls); +// } } paramsType.add(paramType); @@ -746,11 +753,11 @@ if (specParams.size() == paramsSize) { for (int i = 0; i < paramsSize - 1; i++) { CsmSpecializationParameter specParam1 = specParams.get(i); - CsmSpecializationParameter param1 = params.get(i); + CsmSpecializationParameter param1 = params.get(i).first(); // for (int j = i + 1; j < paramsSize; j++) { int j = i + 1; CsmSpecializationParameter specParam2 = specParams.get(j); - CsmSpecializationParameter param2 = params.get(j); + CsmSpecializationParameter param2 = params.get(j).first(); if (specParam1.getText().toString().equals(specParam2.getText().toString()) && param1.getText().toString().equals(param2.getText().toString())) { match += 1; @@ -761,21 +768,29 @@ CsmKindUtilities.isTypeBasedSpecalizationParameter(param1) && CsmKindUtilities.isTypeBasedSpecalizationParameter(param2)) { CsmTypeBasedSpecializationParameter tbp1 = (CsmTypeBasedSpecializationParameter) param1; - CsmType type1 = tbp1.getType(); - if(CsmKindUtilities.isInstantiation(cls)) { - type1 = Instantiation.createType(tbp1.getType(), (Instantiation)cls); - } + CsmType type1 = paramsType.get(i); +// CsmType type1 = tbp1.getType(); +// if(CsmKindUtilities.isInstantiation(cls)) { +// type1 = Instantiation.createType(tbp1.getType(), (Instantiation)cls); +// } CsmClassifier tbsp1Cls = getClassifier(type1); if (tbsp1Cls != null) { CsmTypeBasedSpecializationParameter tbp2 = (CsmTypeBasedSpecializationParameter) param2; - CsmType type2 = tbp2.getType(); - if(CsmKindUtilities.isInstantiation(cls)) { - type2 = Instantiation.createType(tbp2.getType(), (Instantiation)cls); - } + CsmType type2 = paramsType.get(j); +// CsmType type2 = tbp2.getType(); +// if(CsmKindUtilities.isInstantiation(cls)) { +// type2 = Instantiation.createType(tbp2.getType(), (Instantiation)cls); +// } CsmClassifier tbsp2Cls = getClassifier(type2); if(tbsp2Cls != null) { if (tbsp1Cls.getQualifiedName().toString().equals(tbsp2Cls.getQualifiedName().toString())) { match += 1; + } else { + tbsp1Cls = CsmBaseUtilities.getOriginalClassifier(tbsp1Cls, param1.getContainingFile()); + tbsp2Cls = CsmBaseUtilities.getOriginalClassifier(tbsp2Cls, param2.getContainingFile()); + if (tbsp1Cls.getQualifiedName().toString().equals(tbsp2Cls.getQualifiedName().toString())) { + match += 1; + } } } } @@ -785,7 +800,7 @@ } for (int i = 0; i < paramsSize; i++) { CsmSpecializationParameter specParam = specParams.get(i); - CsmSpecializationParameter param = params.get(i); + CsmSpecializationParameter param = params.get(i).first(); if (CsmKindUtilities.isTypeBasedSpecalizationParameter(specParam) && CsmKindUtilities.isTypeBasedSpecalizationParameter(param)) { CsmTypeBasedSpecializationParameter instSpecParam = (CsmTypeBasedSpecializationParameter)param; @@ -1017,12 +1032,12 @@ return ExpressionBasedSpecializationParameterImpl.create(expression, file, start, end); } - public List getInstantiationParams(CsmObject o) { + public List>> getInstantiationParams(CsmObject o) { if (!CsmKindUtilities.isInstantiation(o)) { return Collections.emptyList(); } long time = System.currentTimeMillis(); - List res = new ArrayList(); + List>> res = new ArrayList>>(); CsmInstantiation i = (CsmInstantiation) o; Map m = i.getMapping(); CsmOffsetableDeclaration decl = i.getTemplateDeclaration(); @@ -1032,26 +1047,32 @@ for (CsmTemplateParameter tp : ((CsmTemplate)decl).getTemplateParameters()) { CsmSpecializationParameter sp = m.get(tp); if(sp != null) { - res.add(sp); + List insts = new ArrayList<>(); + insts.add(i); + res.add(Pair.of(sp, insts)); } } } } else { // non first inst - List sps = getInstantiationParams(decl); - for (CsmSpecializationParameter instParam : sps) { + List>> sps = getInstantiationParams(decl); + for (Pair> pair : sps) { + CsmSpecializationParameter instParam = pair.first(); + List instantiations = pair.second(); if (CsmKindUtilities.isTypeBasedSpecalizationParameter(instParam) && CsmKindUtilities.isTemplateParameterType(((CsmTypeBasedSpecializationParameter) instParam).getType())) { CsmTemplateParameterType paramType = (CsmTemplateParameterType) ((CsmTypeBasedSpecializationParameter) instParam).getType(); CsmSpecializationParameter newTp = m.get(paramType.getParameter()); if (newTp != null && newTp != instParam) { - res.add(newTp); + instantiations.clear(); + res.add(Pair.of(newTp, instantiations)); } else { - res.add(instParam); + res.add(pair); } } else { - res.add(instParam); + res.add(pair); } + instantiations.add(i); } } time = System.currentTimeMillis() - time; @@ -1059,6 +1080,14 @@ return res; } + private List getPlainParams(List>> instParams) { + List params = new ArrayList<>(instParams.size()); + for (Pair> pair : instParams) { + params.add(pair.first()); + } + return params; + } + private CsmClassForwardDeclaration findCsmClassForwardDeclaration(CsmScope scope, CsmClass cls) { if (scope != null) { if (CsmKindUtilities.isFile(scope)) { diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/VariableProvider.java b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/VariableProvider.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/VariableProvider.java +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/VariableProvider.java @@ -67,6 +67,7 @@ import org.netbeans.modules.cnd.api.model.CsmTemplateParameterType; import org.netbeans.modules.cnd.api.model.CsmType; import org.netbeans.modules.cnd.api.model.CsmTypeBasedSpecializationParameter; +import org.netbeans.modules.cnd.api.model.deep.CsmExpression; import org.netbeans.modules.cnd.api.model.services.CsmClassifierResolver; import org.netbeans.modules.cnd.api.model.services.CsmInstantiationProvider; import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities; @@ -91,7 +92,7 @@ */ public class VariableProvider { private static final Logger LOG = Logger.getLogger(VariableProvider.class.getSimpleName()); - public static final int INFINITE_RECURSION = 10; + public static final int INFINITE_RECURSION = 16; private final int level; private CsmOffsetableDeclaration decl; @@ -142,6 +143,18 @@ } } else if (CsmKindUtilities.isTypeBasedSpecalizationParameter(spec)) { CsmTypeBasedSpecializationParameter specParameter = (CsmTypeBasedSpecializationParameter) spec; + +// TODO: think about param decl and appropriate mapping (could be necessary if parameter is instantiation itself) +// CsmOffsetableDeclaration paramContextDecl = decl; +// MapHierarchy paramMapping = mapping; +// +// CsmType specParamType = specParameter.getType(); +// CsmClassifier specParamCls = specParamType.getClassifier(); +// if (CsmKindUtilities.isInstantiation(specParamCls) && CsmKindUtilities.isOffsetableDeclaration(specParamCls)) { +// paramContextDecl = (CsmOffsetableDeclaration) specParamCls; +// paramMapping = TemplateUtils.gatherMapping((CsmInstantiation) paramContextDecl); +// } + Object eval = new ExpressionEvaluator(level+1).eval(specParameter.getText().toString(), decl, specParameter.getContainingFile(), specParameter.getStartOffset(), specParameter.getEndOffset(), mapping); if (eval instanceof Integer) { return (Integer) eval; @@ -156,12 +169,20 @@ if (classMembers.hasNext()) { CsmMember member = classMembers.next(); if(member.isStatic() && CsmKindUtilities.isField(member) && member.getName().toString().equals(variableName)) { + CsmExpression expr = ((CsmField)member).getInitialValue(); if(CsmKindUtilities.isInstantiation(member)) { - Object eval = new ExpressionEvaluator(level+1).eval(((CsmField)member).getInitialValue().getText().toString(), member.getContainingClass(), getMapping((CsmInstantiation) member)); + Object eval = new ExpressionEvaluator(level+1).eval( + expr.getText().toString(), + member.getContainingClass(), + expr.getContainingFile(), + expr.getStartOffset(), + expr.getEndOffset(), + getMapping((CsmInstantiation) member) + ); if (eval instanceof Integer) { return (Integer) eval; } - } else if (((CsmField)member).getInitialValue() != null) { + } else if (expr != null) { Object eval = new ExpressionEvaluator(level+1).eval(((CsmField)member).getInitialValue().getText().toString(), member.getContainingClass(), Collections.emptyMap()); if (eval instanceof Integer) { return (Integer) eval; @@ -171,7 +192,7 @@ } } - boolean executeSimpleResolution = !(TraceFlags.EXPRESSION_EVALUATOR_DEEP_VARIABLE_PROVIDER && variableName.contains("<")); // NOI18N + boolean executeSimpleResolution = false;// !(TraceFlags.EXPRESSION_EVALUATOR_DEEP_VARIABLE_PROVIDER && variableName.contains("<")); // NOI18N if (executeSimpleResolution) { CsmObject o = null; @@ -242,9 +263,9 @@ } } - if(CsmKindUtilities.isInstantiation(decl)) { - type = Instantiation.createType(type, (Instantiation)decl); - } +// if(CsmKindUtilities.isInstantiation(decl)) { +// type = Instantiation.createType(type, (Instantiation)decl); +// } CsmClassifier originalClassifier = CsmClassifierResolver.getDefault().getOriginalClassifier(type.getClassifier(), decl.getContainingFile()); if (CsmKindUtilities.isTemplate(originalClassifier)) { diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/parser/Evaluator.g b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/parser/Evaluator.g --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/parser/Evaluator.g +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/impl/services/evaluator/parser/Evaluator.g @@ -37,12 +37,20 @@ ; multExpr returns [int value] - : e=atom {$value = $e.value;} (STAR e=atom {$value *= $e.value;})* + : e=unaryExpr {$value = $e.value;} (STAR e=unaryExpr {$value *= $e.value;})* + ; + +unaryExpr returns [int value] + : e=atom {$value = $e.value;} + | NOT e=unaryExpr {$value = ($e.value == 0 ? 1 : 0);} ; atom returns [int value] - : DECIMALINT {$value = (($DECIMALINT.text) == null) ? 0 : Integer.parseInt(($DECIMALINT.text).replaceAll("[a-z,A-Z,_].*", "")) ;} - | id = qualified_id + : + DECIMALINT {$value = (($DECIMALINT.text) == null) ? 0 : Integer.parseInt(($DECIMALINT.text).replaceAll("[a-z,A-Z,_].*", "")) ;} + | + (LITERAL_const)* + id = qualified_id { $value = vp==null?0:vp.getValue($id.q); //Integer v = (Integer)memory.get($IDENT.text); @@ -69,11 +77,7 @@ IDENT {q += $IDENT.text;} ( - LESSTHAN - {q += "<";} - (x=~GREATERTHAN {q += $x.text;})* - GREATERTHAN - {q += ">";} + inner = balance_less_greater {q += $inner.s;} )? ) ; @@ -84,7 +88,7 @@ SCOPE { s += "::";} )? ( - sp = scope_override_part + (IDENT (balance_less_greater)? SCOPE)=> sp = scope_override_part { s += ($sp.s != null) ? $sp.s : ""; } @@ -98,23 +102,30 @@ s += $IDENT.text; } ( - LESSTHAN - {s += "<";} - (x=~GREATERTHAN {s += $x.text;})* - GREATERTHAN - {s += ">";} + inner = balance_less_greater {s += $inner.s;} )? SCOPE { s += "::"; } - ((IDENT SCOPE) => sp = scope_override_part)? + ((IDENT (balance_less_greater)? SCOPE)=> sp = scope_override_part)? { s += ($sp.s != null) ? $sp.s : ""; } ; +balance_less_greater returns [String s = ""] + : + LESSTHAN {s += "<";} + ( + (LESSTHAN)=> inner = balance_less_greater {s += $inner.s;} + | + other = (~GREATERTHAN) {s += $other.text;} + )* + GREATERTHAN {s += ">";} + ; + // Suppressing warnings "no lexer rule corresponding to token" fragment IDENT: ' '; fragment DECIMALINT: ' '; @@ -124,6 +135,7 @@ fragment STAR: ' '; fragment LESSTHAN: ' '; fragment GREATERTHAN: ' '; +fragment NOT: ' '; fragment SCOPE: ' '; @@ -134,3 +146,5 @@ fragment LITERAL_true: ' '; fragment LITERAL_false: ' '; +fragment LITERAL_const: ' '; + diff --git a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/util/MapHierarchy.java b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/util/MapHierarchy.java --- a/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/util/MapHierarchy.java +++ b/cnd.modelimpl/src/org/netbeans/modules/cnd/modelimpl/util/MapHierarchy.java @@ -66,6 +66,12 @@ push(map); } + public MapHierarchy(MapHierarchy mapHierarchy) { + for (Map map : mapHierarchy.maps) { + push(map); + } + } + public void push(Map map) { maps.push(map); } diff --git a/cnd.modelutil/src/org/netbeans/modules/cnd/modelutil/CsmUtilities.java b/cnd.modelutil/src/org/netbeans/modules/cnd/modelutil/CsmUtilities.java --- a/cnd.modelutil/src/org/netbeans/modules/cnd/modelutil/CsmUtilities.java +++ b/cnd.modelutil/src/org/netbeans/modules/cnd/modelutil/CsmUtilities.java @@ -83,6 +83,7 @@ import org.netbeans.modules.cnd.utils.CndPathUtilities; import org.netbeans.modules.cnd.utils.CndUtils; import org.netbeans.modules.cnd.utils.FSPath; +import org.netbeans.modules.cnd.utils.MutableObject; import org.netbeans.modules.editor.NbEditorUtilities; import org.openide.awt.StatusDisplayer; import org.openide.cookies.EditorCookie; @@ -1152,11 +1153,22 @@ * @return last type */ public static CsmType iterateTypeChain(CsmType type, Predicate stopFilter) { + return iterateTypeChain(type, stopFilter, 50); + } + + /** + * Iterates type chain until end is reached or stopFilter returned true + * @param type from iterate should start + * @param stopFilter + * @param maxDepth - max number of iterations + * @return last type + */ + public static CsmType iterateTypeChain(CsmType type, Predicate stopFilter, int maxDepth) { CsmType lastNestedType = type; Set antiLoop = new HashSet(); - while (type != null && !antiLoop.contains(type) && antiLoop.size() < 50) { + while (type != null && !antiLoop.contains(type) && antiLoop.size() < maxDepth) { lastNestedType = type; if (stopFilter.check(type)) { @@ -1175,7 +1187,43 @@ } return lastNestedType; - } + } + +// public static CsmType checkPointerDepth(CsmType type, int depth, int maxIterations) { +// final MutableObject result = new MutableObject<>(0); +// iterateTypeChain(type, new Predicate() { +// +// @Override +// public boolean check(CsmType value) { +// if (value.isPointer()) { +// result.value += value.getPointerDepth(); +// } +// return false; +// } +// +// }, maxDepth); +// return result.value; +// } +// +// public static int checkReference(CsmType type, int maxDepth) { +// final MutableObject result = new MutableObject<>(0); +// iterateTypeChain(type, new Predicate() { +// +// @Override +// public boolean check(CsmType value) { +// if (value.isReference()) { +// if (value.isRValueReference()) { +// result.value = 2; +// } +// result.value = 1; +// return true; +// } +// return false; +// } +// +// }, maxDepth); +// return result.value; +// } //-----------------------------------------------------------------