protected int diffProvides(JCProvides oldT, JCProvides newT, int[] bounds) { int localPointer = bounds[0]; // service int[] servBounds = getBounds(oldT.serviceName); copyTo(localPointer, servBounds[0]); localPointer = diffTree(oldT.serviceName, newT.serviceName, servBounds); // implementations int posHint; if (oldT.implNames == null || oldT.implNames.isEmpty()) { posHint = endPos(oldT) - 1; } else { posHint = oldT.implNames.iterator().next().getStartPosition(); } if (newT.implNames != null && !newT.implNames.isEmpty()) //do not copy the "with" keyword: copyTo(localPointer, localPointer = posHint); PositionEstimator est = EstimatorFactory.providesWith(oldT.implNames, newT.implNames, diffContext); localPointer = diffList2(oldT.implNames, newT.implNames, posHint, est); copyTo(localPointer, bounds[1]); return bounds[1]; }
@Override public void visitProvides(JCProvides tree) { Type st = attr.attribType(tree.serviceName, env, syms.objectType); Type it = attr.attribType(tree.implName, env, st); ClassSymbol service = (ClassSymbol) st.tsym; ClassSymbol impl = (ClassSymbol) it.tsym; if ((impl.flags() & ABSTRACT) != 0) { log.error(tree.implName.pos(), Errors.ServiceImplementationIsAbstract(impl)); } else if (impl.isInner()) { log.error(tree.implName.pos(), Errors.ServiceImplementationIsInner(impl)); } else if (service.isInner()) { log.error(tree.serviceName.pos(), Errors.ServiceDefinitionIsInner(service)); } else { MethodSymbol constr = noArgsConstructor(impl); if (constr == null) { log.error(tree.implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl)); } else if ((constr.flags() & PUBLIC) == 0) { log.error(tree.implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl)); } } if (st.hasTag(CLASS) && it.hasTag(CLASS)) { Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impl); if (!allProvides.add(d)) { log.error(tree.pos(), Errors.DuplicateProvides(service, impl)); } msym.provides = msym.provides.prepend(d); msym.directives = msym.directives.prepend(d); directiveToTreeMap.put(d, tree); } }
@Override public void visitProvides(JCProvides tree) { }
@Override public void visitProvides(JCProvides tree) { Type st = attr.attribType(tree.serviceName, env, syms.objectType); ClassSymbol service = (ClassSymbol) st.tsym; if (allProvides.containsKey(service)) { log.error(tree.serviceName.pos(), Errors.RepeatedProvidesForService(service)); } ListBuffer<ClassSymbol> impls = new ListBuffer<>(); for (JCExpression implName : tree.implNames) { Type it; boolean prevVisitingServiceImplementation = env.info.visitingServiceImplementation; try { env.info.visitingServiceImplementation = true; it = attr.attribType(implName, env, syms.objectType); } finally { env.info.visitingServiceImplementation = prevVisitingServiceImplementation; } ClassSymbol impl = (ClassSymbol) it.tsym; if ((impl.flags_field & PUBLIC) == 0) { log.error(implName.pos(), Errors.NotDefPublic(impl, impl.location())); } //find provider factory: MethodSymbol factory = factoryMethod(impl); if (factory != null) { Type returnType = factory.type.getReturnType(); if (!types.isSubtype(returnType, st)) { log.error(implName.pos(), Errors.ServiceImplementationProviderReturnMustBeSubtypeOfServiceInterface); } } else { if (!types.isSubtype(it, st)) { log.error(implName.pos(), Errors.ServiceImplementationMustBeSubtypeOfServiceInterface); } else if ((impl.flags() & ABSTRACT) != 0) { log.error(implName.pos(), Errors.ServiceImplementationIsAbstract(impl)); } else if (impl.isInner()) { log.error(implName.pos(), Errors.ServiceImplementationIsInner(impl)); } else { MethodSymbol constr = noArgsConstructor(impl); if (constr == null) { log.error(implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl)); } else if ((constr.flags() & PUBLIC) == 0) { log.error(implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl)); } } } if (it.hasTag(CLASS)) { if (allProvides.computeIfAbsent(service, s -> new HashSet<>()).add(impl)) { impls.append(impl); } else { log.error(implName.pos(), Errors.DuplicateProvides(service, impl)); } } } if (st.hasTag(CLASS) && !impls.isEmpty()) { Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impls.toList()); msym.provides = msym.provides.prepend(d); msym.directives = msym.directives.prepend(d); directiveToTreeMap.put(d, tree); } }
private void checkForCorrectness() { for (Directive.ProvidesDirective provides : msym.provides) { JCProvides tree = directiveToTreeMap.get(provides); for (ClassSymbol impl : provides.impls) { /* The implementation must be defined in the same module as the provides directive * (else, error) */ PackageSymbol implementationDefiningPackage = impl.packge(); if (implementationDefiningPackage.modle != msym) { // TODO: should use tree for the implentation name, not the entire provides tree // TODO: should improve error message to identify the implementation type log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle)); } /* There is no inherent requirement that module that provides a service should actually * use it itself. However, it is a pointless declaration if the service package is not * exported and there is no uses for the service. */ PackageSymbol interfaceDeclaringPackage = provides.service.packge(); boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym; boolean isInterfaceExportedFromAReadableModule = msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage; if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) { // ok the interface is declared in this module. Let's check if it's exported boolean warn = true; for (ExportsDirective export : msym.exports) { if (interfaceDeclaringPackage == export.packge) { warn = false; break; } } if (warn) { for (UsesDirective uses : msym.uses) { if (provides.service == uses.service) { warn = false; break; } } } if (warn) { log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service)); } } } } }
private void checkForCorrectness() { for (Directive.ProvidesDirective provides : allProvides) { JCProvides tree = directiveToTreeMap.get(provides); /* The implementation must be defined in the same module as the provides directive * (else, error) */ PackageSymbol implementationDefiningPackage = provides.impl.packge(); if (implementationDefiningPackage.modle != msym) { log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle)); } /* There is no inherent requirement that module that provides a service should actually * use it itself. However, it is a pointless declaration if the service package is not * exported and there is no uses for the service. */ PackageSymbol interfaceDeclaringPackage = provides.service.packge(); boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym; boolean isInterfaceExportedFromAReadableModule = msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage; if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) { // ok the interface is declared in this module. Let's check if it's exported boolean warn = true; for (ExportsDirective export : msym.exports) { if (interfaceDeclaringPackage == export.packge) { warn = false; break; } } if (warn) { for (UsesDirective uses : msym.uses) { if (provides.service == uses.service) { warn = false; break; } } } if (warn) { log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service)); } } } }