/* * Copyright (c) 2012-2015, Microsoft Mobile * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.juniversal.translator.csharp; import org.eclipse.jdt.core.dom.*; import org.jetbrains.annotations.Nullable; import org.juniversal.translator.core.BufferTargetWriter; import org.juniversal.translator.core.SourceFileWriter; import org.juniversal.translator.core.Var; import java.util.HashSet; import java.util.Map; import java.util.Set; import static org.juniversal.translator.core.ASTUtil.forEach; import static org.juniversal.translator.core.ASTUtil.isGenericImport; // TODO: Finish this class CompilationUnitWriter extends CSharpASTNodeWriter<CompilationUnit> { CompilationUnitWriter(CSharpSourceFileWriter cSharpASTWriters) { super(cSharpASTWriters); } public void write(CompilationUnit compilationUnit) { copySpaceAndComments(); // First visit & write out the guts of the class, using a BufferTargetWriter to capture all output. We do // this first to capture the usage of anything that needs an explicit "using" statement in C# but doesn't // have an import in Java. The top of the file, with the "using" statements, is written later, down below BufferTargetWriter bufferTargetWriter = new BufferTargetWriter(getSourceFileWriter().getTargetWriter()); try (SourceFileWriter.RestoreTargetWriter ignored = getSourceFileWriter().setTargetWriter(bufferTargetWriter)) { writeNamespaceAndTypeDeclaration(compilationUnit); } @Nullable PackageDeclaration packageDeclaration = compilationUnit.getPackage(); if (packageDeclaration != null) { // TODO: This results in an extra newline normally; distinguish between case where package is only thing on line & multiple things on that line setPositionToEndOfNodeSpaceAndComments(packageDeclaration); } else { setPositionToStartOfNode(compilationUnit); skipSpaceAndComments(); } // Write copySpaceAndComments(); writeUsingStatements(compilationUnit); copySpaceAndComments(); write(bufferTargetWriter); setPositionToEndOfNode(compilationUnit); } private void writeUsingStatements(CompilationUnit compilationUnit) { Map<String, String> annotationMap = getSourceFileWriter().getTranslator().getAnnotationMap(); Set<String> genericUsings = new HashSet<>(); Var<Boolean> wroteUsing = new Var<>(false); forEach(compilationUnit.imports(), (ImportDeclaration importDeclaration) -> { Name importDeclarationName = importDeclaration.getName(); String importDeclarationFullyQualifiedName = importDeclarationName.getFullyQualifiedName(); // Skip imports for the Nullable annotation and mapped annotations if (importDeclarationFullyQualifiedName.equals("org.jetbrains.annotations.Nullable") || annotationMap.containsKey(importDeclarationFullyQualifiedName)) { setPositionToEndOfNode(importDeclaration); return; } if (importDeclaration.isStatic()) throw sourceNotSupported("Static imports aren't currently supported"); if (!(importDeclarationName instanceof QualifiedName)) throw sourceNotSupported("Class import is unexpectedly not a fully qualified name (with a '.' in it)"); QualifiedName qualifiedName = (QualifiedName) importDeclarationName; @Nullable String namespaceToImportForGenericClass = null; if (isGenericImport(importDeclaration)) { namespaceToImportForGenericClass = qualifiedName.getQualifier().getFullyQualifiedName(); if (genericUsings.contains(namespaceToImportForGenericClass)) return; } copySpaceAndComments(); matchAndWrite("import", "using"); copySpaceAndComments(); if (importDeclaration.isOnDemand()) { writeNode(importDeclarationName); skipSpaceAndComments(); match("."); skipSpaceAndComments(); match("*"); } else { if (namespaceToImportForGenericClass != null) { write(namespaceToImportForGenericClass); genericUsings.add(namespaceToImportForGenericClass); setPositionToEndOfNode(qualifiedName); } else { writeNodeAtDifferentPosition(qualifiedName.getName()); write(" = "); writeNode(qualifiedName); } } copySpaceAndComments(); matchAndWrite(";"); wroteUsing.set(true); }); if (wroteUsing.value()) writeln(); for (String extraUsing : getContext().getExtraUsings()) { write("using "); write(extraUsing); writeln(";"); } } private void writeNamespaceAndTypeDeclaration(CompilationUnit compilationUnit) { @Nullable PackageDeclaration packageDeclaration = compilationUnit.getPackage(); int previousIndent = 0; if (packageDeclaration != null) { int previousPosition = getPosition(); setPositionToStartOfNode(packageDeclaration); matchAndWrite("package", "namespace"); copySpaceAndComments(); writeNode(packageDeclaration.getName()); write(" {"); previousIndent = getTargetWriter().incrementAdditionalIndentation(getPreferredIndent()); writeln(); setPosition(previousPosition); } /* if (packageDeclaration != null) return getNamespaceNameForPackageName(packageDeclaration == null ? null : packageDeclaration .getName()); */ AbstractTypeDeclaration firstTypeDeclaration = (AbstractTypeDeclaration) compilationUnit.types().get(0); //copySpaceAndComments(); setPositionToStartOfNode(firstTypeDeclaration); writeNode(firstTypeDeclaration); copySpaceAndComments(); if (packageDeclaration != null) { getTargetWriter().setAdditionalIndentation(previousIndent); writeln(); writeln("}"); } /* writeln(); context.setPosition(firstTypeDeclaration.getStartPosition()); copySpaceAndComments(); // Skip any Javadoc included in the node writeNode(context, firstTypeDeclaration); */ } }