1683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti/* 2683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * Copyright 2016 Federico Tomassetti 3683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * 4683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * Licensed under the Apache License, Version 2.0 (the "License"); 5683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * you may not use this file except in compliance with the License. 6683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * You may obtain a copy of the License at 7683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * 8683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * http://www.apache.org/licenses/LICENSE-2.0 9683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * 10683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * Unless required by applicable law or agreed to in writing, software 11683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * distributed under the License is distributed on an "AS IS" BASIS, 12683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * See the License for the specific language governing permissions and 14683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * limitations under the License. 15683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti */ 16683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti 179c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettipackage com.github.javaparser.symbolsolver.javaparsermodel.contexts; 18d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti 19d787c16867577551b1711d01f382a26af1d7a322Federico Tomassettiimport com.github.javaparser.ast.Node; 20c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassettiimport com.github.javaparser.ast.expr.Expression; 21c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoideimport com.github.javaparser.ast.expr.FieldAccessExpr; 22c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassettiimport com.github.javaparser.ast.expr.MethodCallExpr; 231db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveiraimport com.github.javaparser.ast.expr.NameExpr; 24223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassettiimport com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; 251db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveiraimport com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; 261db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveiraimport com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; 271db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveiraimport com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; 28223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassettiimport com.github.javaparser.resolution.types.ResolvedType; 291e7780e554428a10c73de88ca64e5933b2291593Federico Tomassettiimport com.github.javaparser.symbolsolver.core.resolution.Context; 301db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveiraimport com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; 319c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; 329c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.model.resolution.SymbolReference; 339c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 349c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.model.resolution.Value; 351db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveiraimport com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; 361e7780e554428a10c73de88ca64e5933b2291593Federico Tomassettiimport com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; 37d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti 38b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggenimport java.util.*; 392568d9ebe91ceb0a13c98b16f99593cd22084efaFederico Tomassetti 4099c0277ff34b0d97af1019ac91f20a19db364410Federico Tomassettiimport static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; 41b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggenimport static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode; 42b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggenimport static java.util.Collections.*; 433e4b012ca278ee33e9e02984367028cb1adf4bf5Federico Tomassetti 44d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti/** 45e7704aa00835e056f7870bcb255db697f1f7ca25Federico Tomassetti * @author Federico Tomassetti 46d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti */ 47d787c16867577551b1711d01f382a26af1d7a322Federico Tomassettipublic abstract class AbstractJavaParserContext<N extends Node> implements Context { 48d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti 49d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti protected N wrappedNode; 500e81f51c40996b42cb262dc2397126cee8f60965Federico Tomassetti protected TypeSolver typeSolver; 51d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti 526df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 536df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// Static methods 546df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 5549719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti 56b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen public static SymbolReference<ResolvedValueDeclaration> solveWith(SymbolDeclarator symbolDeclarator, String name) { 57223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti for (ResolvedValueDeclaration decl : symbolDeclarator.getSymbolDeclarations()) { 5849719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti if (decl.getName().equals(name)) { 5949719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti return SymbolReference.solved(decl); 6049719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti } 6149719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti } 62223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti return SymbolReference.unsolved(ResolvedValueDeclaration.class); 6349719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti } 6449719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti 656df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 666df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// Constructors 676df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 686df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti 696df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti public AbstractJavaParserContext(N wrappedNode, TypeSolver typeSolver) { 706df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti if (wrappedNode == null) { 716df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti throw new NullPointerException(); 726df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti } 736df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti this.wrappedNode = wrappedNode; 746df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti this.typeSolver = typeSolver; 756df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti } 766df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti 776df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 786df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// Public methods 796df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 806df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti 81bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti @Override 82bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti public boolean equals(Object o) { 83bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti if (this == o) return true; 84bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti if (o == null || getClass() != o.getClass()) return false; 85bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti 86c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide AbstractJavaParserContext<?> that = (AbstractJavaParserContext<?>) o; 87bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti 88bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti if (wrappedNode != null ? !wrappedNode.equals(that.wrappedNode) : that.wrappedNode != null) return false; 89bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti 90bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti return true; 91bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti } 92bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti 93bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti @Override 94bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti public int hashCode() { 95bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti return wrappedNode != null ? wrappedNode.hashCode() : 0; 96bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti } 97bb4473f790e2da86cdce011f7f867a51883aab48Federico Tomassetti 98535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti @Override 99223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti public Optional<ResolvedType> solveGenericType(String name, TypeSolver typeSolver) { 100535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti Context parent = getParent(); 101535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti if (parent == null) { 102535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti return Optional.empty(); 103535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti } else { 104535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti return parent.solveGenericType(name, typeSolver); 105535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti } 106535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti } 107535dd7001046e740345e2d00cb27f13d69226521Federico Tomassetti 108d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti @Override 109d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti public final Context getParent() { 110b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen Node parent = wrappedNode.getParentNode().orElse(null); 111b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen if (parent instanceof MethodCallExpr) { 112b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen MethodCallExpr parentCall = (MethodCallExpr) parent; 113c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti boolean found = false; 11452b60cf471dc9d7b53d8f22018d9c4e4fcc15923Federico Tomassetti if (parentCall.getArguments() != null) { 11552b60cf471dc9d7b53d8f22018d9c4e4fcc15923Federico Tomassetti for (Expression expression : parentCall.getArguments()) { 116c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti if (expression == wrappedNode) { 117c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti found = true; 118c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti } 119c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti } 120c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti } 121c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti if (found) { 122b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen Node notMethod = parent; 12345175889553f49fd90a2860e9e6fa7869730db71Federico Tomassetti while (notMethod instanceof MethodCallExpr) { 124b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen notMethod = requireParentNode(notMethod); 12545175889553f49fd90a2860e9e6fa7869730db71Federico Tomassetti } 12645175889553f49fd90a2860e9e6fa7869730db71Federico Tomassetti return JavaParserFactory.getContext(notMethod, typeSolver); 127c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti } 128c08a0391fd27b2ecc75a264cce9eb4606d0f7b30Federico Tomassetti } 129b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen Node notMethod = parent; 130cb5ffb7fdd56f1b768d25da330fa3b29ecb74eafFederico Tomassetti while (notMethod instanceof MethodCallExpr || notMethod instanceof FieldAccessExpr) { 131b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen notMethod = notMethod.getParentNode().orElse(null); 13245175889553f49fd90a2860e9e6fa7869730db71Federico Tomassetti } 133478a9ba268137913d67438b1e3c8f61e5e0976a5Federico Tomassetti if (notMethod == null) { 134478a9ba268137913d67438b1e3c8f61e5e0976a5Federico Tomassetti return null; 135478a9ba268137913d67438b1e3c8f61e5e0976a5Federico Tomassetti } 13645175889553f49fd90a2860e9e6fa7869730db71Federico Tomassetti return JavaParserFactory.getContext(notMethod, typeSolver); 137d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti } 138d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti 1396df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 1406df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// Protected methods 1416df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti /// 1426df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti 1436df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti protected Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, String name, TypeSolver typeSolver) { 1446df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti return symbolDeclarator.getSymbolDeclarations().stream() 1456df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti .filter(d -> d.getName().equals(name)) 146b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen .map(Value::from) 1476df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti .findFirst(); 1486df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti } 1496df1aa26f75ff0d716a1290007e2b63cc05001aeFederico Tomassetti 1501db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira protected Collection<ResolvedReferenceTypeDeclaration> findTypeDeclarations(Optional<Expression> optScope, TypeSolver typeSolver) { 1511db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira if (optScope.isPresent()) { 1521db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira Expression scope = optScope.get(); 1531db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira 1541db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira // consider static methods 1551db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira if (scope instanceof NameExpr) { 1561db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira NameExpr scopeAsName = (NameExpr) scope; 1571db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira SymbolReference<ResolvedTypeDeclaration> symbolReference = this.solveType(scopeAsName.getName().getId(), typeSolver); 1581db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira if (symbolReference.isSolved() && symbolReference.getCorrespondingDeclaration().isType()) { 159b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen return singletonList(symbolReference.getCorrespondingDeclaration().asReferenceType()); 1601db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 1611db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 1621db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira 163b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen ResolvedType typeOfScope; 1641db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira try { 1651db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira typeOfScope = JavaParserFacade.get(typeSolver).getType(scope); 1661db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } catch (Exception e) { 167b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen throw new RuntimeException("Issue calculating the type of the scope of " + this, e); 1681db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 1691db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira if (typeOfScope.isWildcard()) { 1701db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) { 171b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen return singletonList(typeOfScope.asWildcard().getBoundedType().asReferenceType().getTypeDeclaration()); 1721db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } else { 173b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen return singletonList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); 1741db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 1751db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } else if (typeOfScope.isArray()) { 1761db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira // method call on array are Object methods 177b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen return singletonList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); 1781db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } else if (typeOfScope.isTypeVariable()) { 1791db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira Collection<ResolvedReferenceTypeDeclaration> result = new ArrayList<>(); 1801db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira for (ResolvedTypeParameterDeclaration.Bound bound : typeOfScope.asTypeParameter().getBounds()) { 1811db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira result.add(bound.getType().asReferenceType().getTypeDeclaration()); 1821db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 1831db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira return result; 184b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen } else if (typeOfScope.isConstraint()) { 185b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen return singletonList(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration()); 1861db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 187b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen return singletonList(typeOfScope.asReferenceType().getTypeDeclaration()); 1881db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 189b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); 190b54617e765d73b3ce0d187cf12ad8da382bce439Danny van Bruggen return singletonList(typeOfScope.asReferenceType().getTypeDeclaration()); 1911db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira } 1921db4cd7914d4f36224a4a8944e546650d5fc5a4dMarcos César de Oliveira 193d787c16867577551b1711d01f382a26af1d7a322Federico Tomassetti} 194