/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2015, MontiCore, All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* ******************************************************************************
*/
package de.monticore.symboltable;
import de.monticore.symboltable.modifiers.AccessModifier;
import de.monticore.symboltable.modifiers.IncludesAccessModifierPredicate;
import de.se_rwth.commons.logging.Log;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Provides helper methods for {@link de.monticore.symboltable.Scope}.
*
* @author Pedram Mir Seyed Nazari
*/
public final class Scopes {
private Scopes(){
}
public static Scope getTopScope(final Scope scope) {
Log.errorIfNull(scope);
Scope currentScope = scope;
while (currentScope.getEnclosingScope().isPresent()) {
currentScope = currentScope.getEnclosingScope().get();
}
return currentScope;
}
public static Optional<GlobalScope> getGlobalScope(final Scope scope) {
Scope topScope = getTopScope(scope);
return (topScope instanceof GlobalScope)
? Optional.of((GlobalScope) topScope)
: Optional.empty();
}
public static Optional<ArtifactScope> getArtifactScope(final Scope scope) {
Log.errorIfNull(scope);
if (scope instanceof ArtifactScope) {
return Optional.of((ArtifactScope) scope);
}
Scope currentScope = scope;
while (currentScope.getEnclosingScope().isPresent()) {
currentScope = currentScope.getEnclosingScope().get();
if (currentScope instanceof ArtifactScope) {
return Optional.of((ArtifactScope)currentScope);
}
}
return Optional.empty();
}
public static boolean isDescendant(final Scope descendant, final Scope ancestor) {
Log.errorIfNull(descendant);
Log.errorIfNull(ancestor);
if (descendant == ancestor) {
return false;
}
Optional<? extends Scope> parent = descendant.getEnclosingScope();
while (parent.isPresent()) {
if (parent.get() == ancestor) {
return true;
}
parent = parent.get().getEnclosingScope();
}
return false;
}
public static Optional<? extends Scope> getFirstShadowingScope(final Scope scope) {
Log.errorIfNull(scope);
Optional<? extends Scope> currentScope = Optional.of(scope);
while (currentScope.isPresent()) {
if (currentScope.get().isShadowingScope()) {
return currentScope;
}
currentScope = currentScope.get().getEnclosingScope();
}
return Optional.empty();
}
public static Collection<? extends Symbol> getAllEncapsulatedSymbols(Scope scope) {
if(scope == null) {
return new LinkedHashSet<>();
}
final Set<Symbol> encapsulatedSymbols = new LinkedHashSet<>();
Scope nextScope = scope;
while (true) {
encapsulatedSymbols.addAll(nextScope.resolveLocally(SymbolKind.KIND));
if (!nextScope.getEnclosingScope().isPresent() || (nextScope.getEnclosingScope().get() instanceof GlobalScope)) {
break;
}
nextScope = nextScope.getEnclosingScope().orElse(null);
}
return encapsulatedSymbols;
}
public static Collection<Symbol> getLocalSymbolsAsCollection(final Scope scope) {
final Set<Symbol> allSymbols = new LinkedHashSet<>();
scope.getLocalSymbols().values().forEach(allSymbols::addAll);
return allSymbols;
}
public static <T extends Symbol> Set<T> filterSymbolsByAccessModifier(AccessModifier modifier, Collection<T> resolvedUnfiltered) {
return new LinkedHashSet<>(resolvedUnfiltered.stream().filter(new IncludesAccessModifierPredicate(modifier)).collect(Collectors.toSet()));
}
}