return convertElementToRuntimeObject(((CtFieldAccess<?>) value).getVariable()); } else if (value instanceof CtNewArray) { return toArray((CtNewArray) value);
private <T> void visitFieldAccess(CtFieldAccess<T> fieldAccess) { if ("class".equals(fieldAccess.getVariable().getSimpleName())) { Class<?> actualClass = fieldAccess.getVariable().getDeclaringType().getActualClass(); if (actualClass != null) { CtLiteral<Class<?>> literal = fieldAccess.getFactory().Core().createLiteral(); literal.setValue(actualClass); setResult(literal); if ("length".equals(fieldAccess.getVariable().getSimpleName())) { CtExpression<?> target = fieldAccess.getTarget(); if (target instanceof CtNewArray<?>) { CtNewArray<?> newArr = (CtNewArray<?>) target; CtLiteral<Number> literal = fieldAccess.getFactory().createLiteral(newArr.getElements().size()); setResult(literal); return; if (fieldAccess.getFactory().Type().ENUM .isSubtypeOf(fieldAccess.getVariable().getDeclaringType())) { CtLiteral<CtFieldReference<?>> l = fieldAccess.getFactory().Core().createLiteral(); l.setValue(fieldAccess.getVariable()); setResult(l); return; CtField<?> f = fieldAccess.getVariable().getDeclaration(); if ((f != null) && f.getModifiers().contains(ModifierKind.FINAL)) { setResult(evaluate(f.getDefaultExpression())); return; setResult(fieldAccess.clone());
/** * In no classpath mode, when we build a field access, we have a binding typed by ProblemBinding. * This binding doesn't contain all information but we can get some of them. * * @param singleNameReference * Used to get the problem binding of the field access and the name of the declaring type. * @return a field access. */ <T> CtFieldAccess<T> createFieldAccessNoClasspath(SingleNameReference singleNameReference) { CtFieldAccess<T> va; if (isLhsAssignment(jdtTreeBuilder.getContextBuilder(), singleNameReference)) { va = jdtTreeBuilder.getFactory().Core().createFieldWrite(); } else { va = jdtTreeBuilder.getFactory().Core().createFieldRead(); } va.setVariable(jdtTreeBuilder.getReferencesBuilder().<T>getVariableReference((ProblemBinding) singleNameReference.binding)); final CtReference declaring = jdtTreeBuilder.getReferencesBuilder().getDeclaringReferenceFromImports(singleNameReference.token); if (declaring instanceof CtTypeReference && va.getVariable() != null) { final CtTypeReference<Object> declaringRef = (CtTypeReference<Object>) declaring; va.setTarget(jdtTreeBuilder.getFactory().Code().createTypeAccess(declaringRef)); va.getVariable().setDeclaringType(declaringRef); va.getVariable().setStatic(true); } return va; }
/** * Creates variable access from a {@link CtVariableReference}. Think to move this method * in the {@link spoon.reflect.factory.CodeFactory} if you think that is a good idea. */ public <T> CtFieldAccess<T> createFieldAccess(CtVariableReference<T> variableReference, CtExpression<?> target, boolean isReadAccess) { CtFieldAccess<T> fieldAccess; if (isReadAccess) { fieldAccess = jdtTreeBuilder.getFactory().Core().createFieldWrite(); } else { fieldAccess = jdtTreeBuilder.getFactory().Core().createFieldRead(); } fieldAccess.setVariable(variableReference); fieldAccess.setTarget(target); return fieldAccess; }
private <T> void printCtFieldAccess(CtFieldAccess<T> f) { enterCtExpression(f); try (Writable _context = context.modify()) { if ((f.getVariable().isStatic() || "class".equals(f.getVariable().getSimpleName())) && f.getTarget() instanceof CtTypeAccess) { _context.ignoreGenerics(true); CtExpression<?> target = f.getTarget(); if (target != null) { boolean isInitializeStaticFinalField = isInitializeStaticFinalField(f.getTarget()); boolean isStaticField = f.getVariable().isStatic(); boolean isImportedField = this.isImported(f.getVariable()); if (target.isImplicit() && !(f.getVariable().getFieldDeclaration() == null && this.env.getNoClasspath())) { final CtField<?> field = f.getVariable().getFieldDeclaration(); if (field != null) { final String fieldName = field.getSimpleName(); CtVariable<?> var = f.getVariable().map(new PotentialVariableDeclarationFunction(fieldName)).first(); if (var != field) { printer.writeComment(f.getFactory().createComment("ERROR: Missing field \"" + f.getVariable().getSimpleName() + "\", please check your model. The code may not compile.", CommentType.BLOCK)).writeSpace(); scan(f.getVariable());
@Override public <T> void visitCtFieldAccess(CtFieldAccess<T> f) { enter(f); scan(f.getVariable()); // scan(fieldAccess.getType()); scan(f.getAnnotations()); scanReferences(f.getTypeCasts()); scan(f.getVariable()); scan(f.getTarget()); exit(f); }
private boolean checkAccessedViaStageRefs(CtExpression<?> target) { if (target == null || target instanceof CtThisAccess) return true; if (target instanceof CtFieldAccess) { CtFieldAccess fieldAccess = (CtFieldAccess) target; CtField field = fieldAccess.getVariable().getDeclaration(); if (field != null && field.getAnnotation(StageRef.class) != null) { return checkAccessedViaStageRefs(fieldAccess.getTarget()); } } return false; }
CtFieldReference<?> ref = fieldAccess.getVariable(); if ("length".equals(ref.getSimpleName())) { if (fieldAccess.getTarget() instanceof CtFieldAccess) { ref = ((CtFieldAccess<?>) fieldAccess.getTarget()).getVariable(); if (Parameters.isParameterSource(ref)) { Object[] value = (Object[]) Parameters.getValue(template, ref.getSimpleName(), null); fieldAccess.replace((CtExpression) fieldAccess.getFactory().Code().createLiteral(value .length)); throw new SkipException(fieldAccess); if (fieldAccess.getParent() instanceof CtArrayAccess) { toReplace = (CtExpression) fieldAccess.getParent(); CtAbstractInvocation<?> inv = (CtAbstractInvocation<?>) fieldAccess.getParent(); int i = inv.getArguments().indexOf(fieldAccess); inv.getArguments().remove(i); inv.getExecutable().getActualTypeArguments().remove(i); for (CtExpression<?> va : vas) { va.setParent(fieldAccess.getParent()); inv.getArguments().add(i, va); inv.getExecutable().getActualTypeArguments().add(i, va.getType());
ref.setDeclaringType(references.getTypeReference(qualifiedNameReference.actualReceiverType)); fa.setVariable(ref); fa.setTarget(factory.Code().createCodeSnippetExpression(typeReference.toString())); other.setVariable(references.getVariableReference(b)); other.setTarget(fa); other.setType(references.getTypeReference(b.type)); } else { other.setType(ref2); int sourceEnd = (int) (positions[i]); final int[] lineSeparatorPositions = context.compilationunitdeclaration.compilationResult.lineSeparatorPositions; fa.setPosition(factory.Core().createSourcePosition(cu, sourceStart, sourceEnd, lineSeparatorPositions)); fa = other; i++; other.setVariable(references.getVariableReference(b)); other.setTarget(va); if (b != null) { other.setType(references.getTypeReference(b.type)); } else { other.setType(ref);
private void guardFieldsAccess() { cxt.allNodes().forEach(node -> { List<CtFieldAccess<?>> fieldAccesses = node.filterBlocksForBuildingDeps((CtFieldAccess<?> fa) -> true); fieldAccesses.forEach((CtFieldAccess fa) -> { CtField<?> field = fa.getVariable().getDeclaration(); if (field != null) { StageModel stage = cxt.getStageModel(field); if (stage != null && stage != node) { CtExpression<?> target = fa.getTarget(); CtTargetedExpression<?, CtExpression<?>> access = stage.fieldAccess(target, field); if (target != null) target.setParent(access); fa.replace(access); } } }); }); }
/** * In no classpath mode, when we build a field access, we have a binding typed by ProblemBinding. * We try to get all information we can get from this binding. * * @param qualifiedNameReference * Used to get the problem binding of the field access and the name of the declaring type. * @return a field access. */ <T> CtFieldAccess<T> createFieldAccessNoClasspath(QualifiedNameReference qualifiedNameReference) { boolean fromAssignment = isLhsAssignment(jdtTreeBuilder.getContextBuilder(), qualifiedNameReference); CtFieldAccess<T> fieldAccess = createFieldAccess(jdtTreeBuilder.getReferencesBuilder().<T>getVariableReference((ProblemBinding) qualifiedNameReference.binding), null, fromAssignment); // In no classpath mode and with qualified name, the type given by JDT is wrong... final char[][] declaringClass = CharOperation.subarray(qualifiedNameReference.tokens, 0, qualifiedNameReference.tokens.length - 1); final MissingTypeBinding declaringType = jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.createMissingType(null, declaringClass); final CtTypeReference<T> declaringRef = jdtTreeBuilder.getReferencesBuilder().getTypeReference(declaringType); fieldAccess.getVariable().setDeclaringType(declaringRef); fieldAccess.getVariable().setStatic(true); fieldAccess.setTarget(jdtTreeBuilder.getFactory().Code().createTypeAccess(declaringRef)); // In no classpath mode and with qualified name, the binding doesn't have a good name. fieldAccess.getVariable() .setSimpleName(createQualifiedTypeName(CharOperation.subarray(qualifiedNameReference.tokens, qualifiedNameReference.tokens.length - 1, qualifiedNameReference.tokens.length))); return fieldAccess; }
@SuppressWarnings("unchecked") public static CtFieldAccess<?> chainToAccess(List<CtField<?>> chain, AccessType accessType) { CtFieldAccess<?> access = null; for (int i = chain.size() - 1; i >= 0; i--) { CtField<?> field = chain.get(i); CoreFactory coreFactory = field.getFactory().Core(); CtFieldAccess acc = accessType == AccessType.Read ? coreFactory.createFieldRead() : coreFactory.createFieldWrite(); acc.setVariable(field.getReference()); acc.setType(field.getType()); acc.setTarget(access); access = acc; } return access; }
/** * Creates a field access from a field reference. * * @param fieldReference * Used to build the spoon variable reference and the type of the field access. * @return a field access. */ <T> CtFieldAccess<T> createFieldAccess(FieldReference fieldReference) { CtFieldAccess<T> fieldAccess; if (isLhsAssignment(jdtTreeBuilder.getContextBuilder(), fieldReference)) { fieldAccess = jdtTreeBuilder.getFactory().Core().createFieldWrite(); } else { fieldAccess = jdtTreeBuilder.getFactory().Core().createFieldRead(); } fieldAccess.setVariable(jdtTreeBuilder.getReferencesBuilder().<T>getVariableReference(fieldReference.binding, fieldReference.token)); fieldAccess.setType(jdtTreeBuilder.getReferencesBuilder().<T>getTypeReference(fieldReference.resolvedType)); return fieldAccess; }
CtClass<?> baseC = p.b; return baseC.getElements((CtFieldAccess<?> fieldAccess) -> { CtField<?> field = fieldAccess.getVariable().getDeclaration(); return field != null && field.getAnnotation(StageRef.class) != null && (fieldAccess instanceof CtFieldRead || CtClass<?> classWhereAccessFound = p.a; CtFieldAccess stageRefAccess = p.b; CtField<?> field = stageRefAccess.getVariable().getDeclaration(); assert field != null; CompilationNode referencingNode = AccessType.Write); assert access != null; stageRefAccess.replace(access); });
@Override public <T> void visitCtFieldAccess(CtFieldAccess<T> fieldAccess) { if (fieldAccess.getVariable().getSimpleName().equals("class")) { Class<?> c = fieldAccess.getVariable().getDeclaringType().getActualClass(); if (c != null) { CtLiteral<Class<?>> l = fieldAccess.getFactory().Core().createLiteral(); l.setValue(c); setResult(l); return; } } if (fieldAccess.getFactory().Type().createReference(Enum.class) .isAssignableFrom(fieldAccess.getVariable().getDeclaringType())) { CtLiteral<CtFieldReference<?>> l = fieldAccess.getFactory().Core().createLiteral(); l.setValue(fieldAccess.getVariable()); setResult(l); return; } CtField<?> f = fieldAccess.getVariable().getDeclaration(); if ((f != null) && f.getModifiers().contains(ModifierKind.FINAL)) { setResult(evaluate(f, f.getDefaultExpression())); return; } setResult(fieldAccess.getFactory().Core().clone(fieldAccess)); }
private void checkFieldsAssignedOnlyWithinNodes() { forEachBaseClass(baseType -> baseType.getElements((CtFieldAccess<?> fieldAccess) -> { CtField<?> field = fieldAccess.getVariable().getDeclaration(); if (field == null) return false; StageModel model = cxt.getStageModel(field); if (model == null) return false; CtElement accessParent = fieldAccess.getParent(); if (!(accessParent instanceof CtAssignment) || ((CtAssignment) accessParent).getAssigned() != fieldAccess) return false; for (CtElement p = accessParent; p != null; p = p.isParentInitialized() ? p.getParent() : null) { if (p instanceof CtMethod) { CtMethod<?> m = (CtMethod<?>) p; if (cxt.getStageModelByInitStage(m) == model || cxt.getStageModelByClose(m) == model || cxt.getStageModelByStageMethod(m) == model) { return false; } } } throw sgce(field + " shouldn't be assigned outside its stage's init() or close()"); })); }
CtExpression<?> access(CompilationNode target, AccessType accessType) { List<CtField<?>> accessPath = accessPath(target); CompilationNode thisNodeToAccess = this; while (!target.rootAccessPath.subList(0, min(thisNodeToAccess.rootAccessPath.size(), target.rootAccessPath.size())) .equals(thisNodeToAccess.rootAccessPath)) { thisNodeToAccess = thisNodeToAccess.parent; } CtFieldAccess<?> access = FieldAccessChains.chainToAccess(accessPath, accessType); CtClass<?> classToMerge = thisNodeToAccess.classesToMerge.get(0); CtThisAccess<?> thisAccess = f.Code().createThisAccess(classToMerge.getReference()); // thisAccess.setImplicit(false); if (access != null) { CtFieldAccess<?> innerMostAccess = access; while (innerMostAccess.getTarget() != null) { innerMostAccess = (CtFieldAccess<?>) innerMostAccess.getTarget(); } innerMostAccess.setTarget(thisAccess); return access; } else { return thisAccess; } }
/** * Creates a variable access. */ public <T> CtVariableAccess<T> createVariableRead(CtVariableReference<T> variable, boolean isStatic) { CtVariableAccess<T> va; if (variable instanceof CtFieldReference) { va = factory.Core().createFieldRead(); // creates a this target for non-static fields to avoid name conflicts... if (!isStatic) { ((CtFieldAccess<T>) va).setTarget(createThisAccess(((CtFieldReference<T>) variable).getDeclaringType())); } } else { va = factory.Core().createVariableRead(); } return va.setVariable(variable); }
@Override public Set<ModifierKind> getModifiers() { CtVariable<?> v = getDeclaration(); if (v != null) { return v.getModifiers(); } // the modifiers of the "class" of AClass.class is the empty set if (this.isParentInitialized() && this.getParent() instanceof CtFieldAccess && ((CtFieldAccess) this.getParent()).getTarget() instanceof CtTypeAccess) { return emptySet(); } Member m = getActualField(); if (m != null) { return RtHelper.getModifiers(m.getModifiers()); } return Collections.emptySet(); }
sourceEnd = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding + i + 1] >>> 32) - 2; other.setPosition(jdtTreeBuilder.getPositionBuilder().buildPosition(sourceStart, sourceEnd)); va = other; i++;