/**
* Copyright (C) 2006-2017 INRIA and contributors
* Spoon - http://spoon.gforge.inria.fr/
*
* This software is governed by the CeCILL-C License under French law and
* abiding by the rules of distribution of free software. You can use, modify
* and/or redistribute the software under the terms of the CeCILL-C license as
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
*
* This program 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 CeCILL-C License for more details.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*/
package spoon.support.reflect.cu;
import spoon.processing.FactoryAccessor;
import spoon.reflect.cu.CompilationUnit;
import spoon.reflect.declaration.CtPackage;
import spoon.reflect.declaration.CtType;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.filter.TypeFilter;
import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static spoon.reflect.ModelElementContainerDefaultCapacities.COMPILATION_UNIT_DECLARED_TYPES_CONTAINER_DEFAULT_CAPACITY;
public class CompilationUnitImpl implements CompilationUnit, FactoryAccessor {
Factory factory;
List<CtType<?>> declaredTypes = new ArrayList<>(COMPILATION_UNIT_DECLARED_TYPES_CONTAINER_DEFAULT_CAPACITY);
CtPackage ctPackage;
public List<CtType<?>> getDeclaredTypes() {
return declaredTypes;
}
File file;
public File getFile() {
return file;
}
public CtType<?> getMainType() {
if (getFile() == null) {
return getDeclaredTypes().get(0);
}
for (CtType<?> t : getDeclaredTypes()) {
String name = getFile().getName();
name = name.substring(0, name.lastIndexOf("."));
if (t.getSimpleName().equals(name)) {
return t;
}
}
throw new RuntimeException(
"inconsistent compilation unit: '"
+ file
+ "': declared types are "
+ getDeclaredTypes());
}
public void setDeclaredTypes(List<CtType<?>> types) {
this.declaredTypes = types;
}
@Override
public CtPackage getDeclaredPackage() {
return ctPackage;
}
@Override
public void setDeclaredPackage(CtPackage ctPackage) {
this.ctPackage = ctPackage;
}
public void setFile(File file) {
this.file = file;
}
@Override
public List<File> getBinaryFiles() {
final List<File> binaries = new ArrayList<>();
final String output = getFactory()
.getEnvironment()
.getBinaryOutputDirectory();
if (output != null) {
final File base = Paths
.get(output, getDeclaredPackage()
.getQualifiedName()
.replace(".", File.separator))
.toFile();
if (base.isDirectory()) {
for (final CtType type : getDeclaredTypes()) {
// Add main type, for instance, 'Foo.class'.
final String nameOfType = type.getSimpleName();
final File fileOfType = new File(
base, nameOfType + ".class");
if (fileOfType.isFile()) {
binaries.add(fileOfType);
}
// Add inner/anonymous types, for instance,
// 'Foo$Bar.class'. Use 'getElements()' rather than
// 'getNestedTypes()' to also fetch inner types of inner
// types of inner types ... and so on.
for (final CtType inner : type.getElements(
new TypeFilter<>(CtType.class))) {
// 'getElements' does not only return inner types but
// also returns 'type' itself. Thus, we need to ensure
// to not add 'type' twice.
if (!inner.equals(type)) {
final String nameOfInner =
nameOfType + "$" + inner.getSimpleName();
final File fileOfInnerType = new File(
base, nameOfInner + ".class");
if (fileOfInnerType.isFile()) {
binaries.add(fileOfInnerType);
}
}
}
}
}
}
return binaries;
}
String originalSourceCode;
public String getOriginalSourceCode() {
try {
if (originalSourceCode == null) {
FileInputStream s = new FileInputStream(getFile());
byte[] elementBytes = new byte[s.available()];
s.read(elementBytes);
s.close();
originalSourceCode = new String(elementBytes);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return originalSourceCode;
}
public int beginOfLineIndex(int index) {
int cur = index;
while (cur >= 0 && getOriginalSourceCode().charAt(cur) != '\n') {
cur--;
}
return cur + 1;
}
public int nextLineIndex(int index) {
int cur = index;
while (cur < getOriginalSourceCode().length()
&& getOriginalSourceCode().charAt(cur) != '\n') {
cur++;
}
return cur + 1;
}
public int getTabCount(int index) {
int cur = index;
int tabCount = 0;
int whiteSpaceCount = 0;
while (cur < getOriginalSourceCode().length()
&& (getOriginalSourceCode().charAt(cur) == ' ' || getOriginalSourceCode()
.charAt(cur) == '\t')) {
if (getOriginalSourceCode().charAt(cur) == '\t') {
tabCount++;
}
if (getOriginalSourceCode().charAt(cur) == ' ') {
whiteSpaceCount++;
}
cur++;
}
tabCount += whiteSpaceCount
/ getFactory().getEnvironment().getTabulationSize();
return tabCount;
}
public Factory getFactory() {
return factory;
}
public void setFactory(Factory factory) {
this.factory = factory;
}
boolean autoImport = true;
public boolean isAutoImport() {
return autoImport;
}
public void setAutoImport(boolean autoImport) {
this.autoImport = autoImport;
}
}