├── .hgignore
├── .hgtags
├── NEWS
├── README.md
├── ctest
├── .cproject
└── .project
├── feature
├── .project
├── build.properties
└── feature.xml
├── lib
└── j2c.cpp
├── plugin
├── .classpath
├── .project
├── .settings
│ ├── org.eclipse.jdt.core.prefs
│ └── org.eclipse.ltk.core.refactoring.prefs
├── META-INF
│ └── MANIFEST.MF
├── build.properties
├── icons
│ └── sample.gif
├── plugin.xml
└── src
│ └── se
│ └── arnetheduck
│ └── j2c
│ ├── Activator.java
│ ├── handlers
│ ├── HandlerHelper.java
│ ├── TestHandler.java
│ └── TransformHandler.java
│ ├── resources
│ ├── Array.hpp
│ ├── Main.cpp.tmpl
│ ├── Makefile.tmpl
│ ├── ObjectArray.hpp
│ ├── SubArray.hpp
│ ├── finally.hpp
│ ├── java_cast.hpp
│ ├── npc.hpp
│ └── synchronized.hpp
│ ├── snippets
│ ├── GetSetSnippet.java
│ └── ReplaceInvocation.java
│ └── transform
│ ├── BindingComparator.java
│ ├── CName.java
│ ├── DepInfo.java
│ ├── EmptySnippet.java
│ ├── FileUtil.java
│ ├── ForwardWriter.java
│ ├── Header.java
│ ├── HeaderWriter.java
│ ├── Impl.java
│ ├── ImplWriter.java
│ ├── InitInfo.java
│ ├── MainWriter.java
│ ├── MakefileWriter.java
│ ├── Predicate.java
│ ├── Snippet.java
│ ├── Stats.java
│ ├── StubWriter.java
│ ├── TransformUtil.java
│ ├── TransformWriter.java
│ ├── Transformer.java
│ ├── TypeBindingHeaderWriter.java
│ ├── TypeInfo.java
│ ├── TypeInfoVisitor.java
│ ├── TypeUtil.java
│ └── UnitInfo.java
└── test
├── .classpath
├── .project
├── .settings
└── org.eclipse.jdt.ui.prefs
└── src
├── Sort.java
└── se
└── arnetheduck
└── j2c
└── test
├── Annot.java
├── BoxTest.java
├── BridgeTest.java
├── CastTest.java
├── ClassLiteralTest.java
├── ConstructorTest.java
├── DefaultVirtual.java
├── Empty.java
├── EnumTest.java
├── ExtendsTest.java
├── ForTest.java
├── Friends.java
├── GenericTest.java
├── Hello.java
├── IEmpty.java
├── ISub.java
├── ITest.java
├── IfElseTest.java
├── Infix.java
├── InitTest.java
├── LabelTest.java
├── LiteralTest.java
├── LocalClassTest.java
├── MainTest.java
├── Method.java
├── Names.java
├── NestedAccessTest.java
├── NestedTest.java
├── Object.java
├── ParamConstructor.java
├── PrimitiveTest.java
├── ReturnTest.java
├── ShiftTest.java
├── StaticImportTest.java
├── StringTest.java
├── Sub.java
├── SuperTest.java
├── SyncTest.java
├── SyntheticTest.java
├── TryTest.java
├── VarargTest.java
├── Volatile.java
├── a
└── Empty.java
├── array
├── Classes.java
├── Covariance.java
├── Interfaces.java
├── Mixed.java
├── MultiArray.java
├── Primitives.java
├── TestArray.java
└── TestArrayArray.java
├── asm
└── int32_t.java
├── b
└── OtherArrayTest.java
├── enums
├── AnonymousConstants.java
├── Ctor.java
├── EnumBridge.java
├── ImplicitMethods.java
└── SimpleEnum.java
├── generics
├── BaseCall.java
├── DiamondImplements.java
├── Fields.java
├── GenHiding.java
├── GenericBoxing.java
├── Implement.java
├── MethodInvocationCast.java
├── MultiBound.java
├── NamedLocal.java
├── Raw.java
├── ReturnCovariance.java
└── SuperBridgeCall.java
├── hiding
├── A.java
├── B.java
├── HiddenByType.java
├── HiddenField.java
└── HiddenMethod.java
├── init
├── ConstExpr.java
├── Constructor.java
├── InitBeforeCons.java
├── Instance.java
├── PrivateConstructor.java
├── Static.java
├── StaticClosure.java
└── StringDep.java
├── interfaces
├── SameName.java
├── SameNameOverload.java
└── UnqualifiedInterfaceField.java
├── methods
├── AbstractWithInterface.java
├── AmbiguousOverloads.java
├── AmbiguousSuper.java
├── BaseCall.java
├── BaseFinalImpl.java
├── BaseImplements.java
├── ConstVars.java
├── CovariantCircular.java
├── CovariantCircularDeep.java
├── CovariantInterface.java
├── CovariantReturn.java
├── CrossCovariant.java
├── DefaultVirtualOverride.java
├── DiamondImplements.java
├── DoubleImplements.java
├── DoubleInheritedImplements.java
├── GenericBaseImplements.java
├── GenericDoubleImplements.java
├── Hiding.java
├── HidingStatic.java
├── Implement.java
├── ImplementOverloads.java
├── ImportStaticCall.java
├── InheritedCovariant.java
├── Overrides.java
├── SimpleImplements.java
├── StaticInvokes.java
├── UnrelatedCovariant.java
└── Using.java
├── nesting
├── Annot.java
├── ClosureInInitializer.java
├── ClosureNames.java
├── Deep.java
├── DeepSiblings.java
├── DoubleAnon.java
├── FieldInit.java
├── GenericQualifiedThis.java
├── LocalNamed.java
├── LocalNested.java
├── LocalOverload.java
├── LocalPrivateCtor.java
├── MethodParam.java
├── NewPrimary.java
├── OuterSubclass.java
├── QualifiedThisSuper.java
├── SameName.java
├── Siblings.java
├── StaticNonStatic.java
└── Subclass.java
└── switchx
├── Empty.java
├── InterfaceValues.java
├── NestedEnumSwitch.java
├── SwitchEnum.java
└── SwitchTest.java
/.hgignore:
--------------------------------------------------------------------------------
1 | syntax: glob
2 | bin/*
3 | *.o
4 |
5 | syntax: regexp
6 | ^ctest/[^.].+
7 |
--------------------------------------------------------------------------------
/.hgtags:
--------------------------------------------------------------------------------
1 | 3004f66e087bd43824775f245874d25dd79ea337 0.1.0
2 | 33a86471b626184e3cb1955e2490756178ea3665 0.2.0
3 | b102a36aa2a5b8c82445c5472133f279632028c9 0.2.1
4 | 6c1f84ab525058f7759d97f3610d545c63d8c4df 0.2.2
5 | fcbc91b7c0b96a12a683dde1918ca88a380f8a35 0.3.0
6 | 92411fafce421efc3d39a6e9bae82e3a6034d3fe 0.3.1
7 | 1208612a2e6c2f0409a61f976fa7dac26fcd0c02 0.4.0
8 | 301a66667950e7b7b1fee1fb178a320f58c45321 0.5.0
9 |
--------------------------------------------------------------------------------
/NEWS:
--------------------------------------------------------------------------------
1 | 0.5.0
2 | -----
3 | * Multiselect translates all selected items (have to be from same project)
4 | * Initialize members in headers, don't generate default constructors that shouldn't be there
5 | * Implement values and valueOf for enums, and fix their name / ordinal
6 | * Range-for-loops when looping over arrays
7 | * Use auto when declaring variables
8 | * Use single template class for arrays instead of generated .hpp/.cpp pairs
9 | * Bugfixes
10 | * Drop unused CDT dependency (might come back)
11 | * Release through update site
12 |
13 | 0.4.0
14 | -----
15 | * Source and header files are now both generated in the src directory
16 | * Avoid generating unnecessary clinit's/ctor:s
17 | * Report name of unimplemented stubs
18 | * Implement volatile using std::atomic
19 | * Other small fixes
20 |
21 | 0.3.1
22 | -----
23 | * Fix too few stubs and too many natives being generated in certain cases
24 |
25 | 0.3.0
26 | -----
27 | * No more mangling of variable names (unless unavoidable)
28 | * Handle more corner cases
29 | * Static initalization / construction fixes
30 | * Better switch break handling
31 | * Throw correct exception on cast failure
32 | * Null checking
33 | * Handle cyclic dependencies due to return type covariance
34 | * Minimum Java required version is now 1.6 (instead of 1.7)
35 |
36 | 0.2.2
37 | -----
38 | * Handle more selection types in the project explorer
39 |
40 | 0.2.1
41 | -----
42 | * Also show translate menu item in project explorer
43 |
44 | 0.2.0
45 | -----
46 | * Successfully converts most of OpenJDK 6!
47 |
48 | 0.1.0
49 | -----
50 | * Initial release
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Introduction
2 | --
3 | J2C will convert Java code into hopefully compilable C++(11) code. It works on
4 | source level, translating Java source code constructs into their rough
5 | equivalents in C++ . The output will be reasonably valid C++ code that looks a
6 | lot like its Java counterpart and hopefully works mostly the same.
7 |
8 | The translation is based on The Java Language Specification, Third Edition, by
9 | Gosling, James and Joy, Bill and Steele, Guy and Bracha, Gilad (that's
10 | Java 1.6). The translated code should be valid as specified by the ISO/IEC
11 | 14882:2011 C++ standard (or C++11 as the rest of the world knows it).
12 |
13 | *The generated code won't work out of the box - you need to remove or implement
14 | dependencies such as the JRE.*
15 |
16 | Status
17 | --
18 | This project is an idea I've been wanting to try out written down in code.
19 | Think of it as a paper napkin with some notes on, but in this case, the notes
20 | compile and sometimes spit out working stuff. In other words, no guarantees
21 | and no quality control label.
22 |
23 | That said, j2c successfully converts most of OpenJDK 6 and SWT 3.7 to C++
24 | that compiles and passes a quick ocular inspection. Most *language* features
25 | of Java 1.6 are covered (i e you'll still need a JDK and runtime).
26 |
27 | With a few patches and implementations of native methods in the converted
28 | OpenJDK code, the included Hello test prints it's message. A more complete
29 | example would need a more complete runtime, either by implementing the native
30 | and JVM parts of a class library or by implementing the stubs that are
31 | generated for missing dependencies.
32 |
33 | This is the first time I write an Eclipse plugin, so be nice.
34 |
35 | Install / Run
36 | --
37 | J2C comes in the form of an Eclipse plugin. You need at least Eclipse 3.8+ and
38 | Java 1.6+ to run this plugin!
39 |
40 | The most recent version of the project is available as source code. You can get
41 | it either from Bitbucket (https://bitbucket.org/arnetheduck/j2c/)
42 | or github (https://github.com/arnetheduck/j2c).
43 |
44 | From time to time, a release may appear at the Bitbucket site - see
45 | https://bitbucket.org/arnetheduck/j2c/downloads . About that same
46 | time, the update site (https://bitbucket.org/arnetheduck/j2c.site/raw/default/)
47 | should be updated.
48 |
49 | If you installed via site, it should just work.
50 |
51 | If you downloaded the jar, copy it to `$ECLIPSE_HOME/dropins`.
52 |
53 | If you downloaded the source code you'll have run the plugin by opening the
54 | project in Eclipse and starting a new Eclipse test instance by using the run
55 | button in the plugin.xml overview.
56 |
57 | Once you have the plugin running, set up your Java code as a Java
58 | Project. Eclipse must be able to compile your code for J2C do to its work!
59 |
60 | Once the Java Project is set up (with all dependencies etc), you can run J2C by
61 | right-clicking the project (or a class/package) in the 'Project Explorer' or
62 | 'Package Explorer' view and choosing the 'Translate to C++' option. You will
63 | need to create a folder for the conversion output - the plugin will tell you
64 | where.
65 |
66 | The generated code will contain references to your JRE (stuff from the `java.*`
67 | packages), as well as some generic helpers. The JRE dependencies will likely be
68 | stubbed out in the ext folder in the generated code, and trivial, non-working
69 | implementations of the rest can be found in j2c.cpp. You'll need to supplant
70 | the converted code with implementations of all JRE features you're using,
71 | or replace them manually to use equivalents from C++ libraries such as STL.
72 |
73 | Testing
74 | --
75 | The test project contains a few cases which should be handled correctly by the
76 | translator (by correctly, I mean that they compile with g++ 4.7). You'll find
77 | a CDT project in ctest that builds using the generated Makefile after running
78 | the plugin on the test project.
79 |
80 | Output
81 | --
82 | For each Java class, j2c will output a header file and its implementation.
83 | Inner classes end up in separate .h/.cpp pairs. Native method stubs will be
84 | put in a separate file for your editing pleasure.
85 |
86 | Classes for which there is no source will have a header written as well as
87 | a stub file with empty implementations. Throughout, the heap will be used
88 | to allocate class instances but no attempt is made to collect garbage -
89 | I recommend Boehm's garbage collector for that.
90 |
91 | What's missing (that I can think of right now)
92 | --
93 | * Reflection
94 | * Anything involving byte code (class loading, dynamic code generation, etc)
95 | * Command line support / build integration
96 |
97 | Helping out
98 | --
99 | Patches and forks are most welcome, as is testing, but please don't report
100 | issues unless you also attach a simple test case.
101 |
102 | Final words
103 | --
104 | Send me a note if you manage (or not) to do something useful with this
105 | converter!
106 |
107 | Licensing
108 | --
109 | The project is licensed under the Eclipse Public License 1.0.
110 |
111 | Thanks
112 | --
113 | No animals were hurt while writing this code, but the Nightwatchman
114 | might have sore fingers and throat from all that playing...
115 |
116 | Have fun,
117 | Jacek Sieka (arnetheduck using google mail point com)
118 |
--------------------------------------------------------------------------------
/ctest/.cproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/ctest/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | se.arnetheduck.j2c.ctest
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 | ?children?
14 | ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|?name?=entry\\\\\\\|\\\|\||
15 |
16 |
17 | ?name?
18 |
19 |
20 |
21 | org.eclipse.cdt.make.core.append_environment
22 | true
23 |
24 |
25 | org.eclipse.cdt.make.core.autoBuildTarget
26 | all
27 |
28 |
29 | org.eclipse.cdt.make.core.buildArguments
30 | -k -j
31 |
32 |
33 | org.eclipse.cdt.make.core.buildCommand
34 | make
35 |
36 |
37 | org.eclipse.cdt.make.core.cleanBuildTarget
38 | clean
39 |
40 |
41 | org.eclipse.cdt.make.core.contents
42 | org.eclipse.cdt.make.core.activeConfigSettings
43 |
44 |
45 | org.eclipse.cdt.make.core.enableAutoBuild
46 | false
47 |
48 |
49 | org.eclipse.cdt.make.core.enableCleanBuild
50 | true
51 |
52 |
53 | org.eclipse.cdt.make.core.enableFullBuild
54 | true
55 |
56 |
57 | org.eclipse.cdt.make.core.fullBuildTarget
58 | all
59 |
60 |
61 | org.eclipse.cdt.make.core.stopOnError
62 | false
63 |
64 |
65 | org.eclipse.cdt.make.core.useDefaultBuildCmd
66 | true
67 |
68 |
69 |
70 |
71 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
72 | full,incremental,
73 |
74 |
75 |
76 |
77 |
78 | org.eclipse.cdt.core.cnature
79 | org.eclipse.cdt.core.ccnature
80 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
81 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
82 |
83 |
84 |
--------------------------------------------------------------------------------
/feature/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | se.arnetheduck.j2c.feature
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.pde.FeatureBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.pde.FeatureNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/feature/build.properties:
--------------------------------------------------------------------------------
1 | bin.includes = feature.xml
2 |
--------------------------------------------------------------------------------
/lib/j2c.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | using namespace java::lang;
11 |
12 | void lock(Object*) { }
13 |
14 | void unlock(Object*) { }
15 |
16 | String *java::lang::operator "" _j(const char16_t* p, size_t n) {
17 | auto x = new char16_tArray(p, n);
18 | auto s = new String(x, true);
19 | return s->intern();
20 | }
21 |
22 | Class *class_(const char16_t *s, int n) {
23 | return Class::forName(operator "" _j(s, n));
24 | }
25 |
26 | void unimplemented_(const char16_t *name) {
27 | std::wcerr << "call to unimplemented: ";
28 | // Not quite right but good enough ;)
29 | while(*name) std::wcerr << static_cast(*(name++));
30 | std::wcerr << std::endl;
31 | }
32 |
33 | void init_jvm() {
34 | // This will be called by the generated main file before running any java code
35 | // Use it to initialize system properties and other stuff the JVM should provide
36 | }
37 |
38 | java::lang::StringArray* make_args(int args, char** argv) {
39 | // Helper that should convert strings passed to app into
40 | // StringArray passed to java main
41 | return nullptr;
42 | }
43 |
--------------------------------------------------------------------------------
/plugin/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/plugin/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | se.arnetheduck.j2c
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.pde.ManifestBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.pde.SchemaBuilder
20 |
21 |
22 |
23 |
24 |
25 | org.eclipse.pde.PluginNature
26 | org.eclipse.jdt.core.javanature
27 |
28 |
29 |
--------------------------------------------------------------------------------
/plugin/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.6
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.6
12 |
--------------------------------------------------------------------------------
/plugin/.settings/org.eclipse.ltk.core.refactoring.prefs:
--------------------------------------------------------------------------------
1 | #Thu Jan 26 22:24:51 CET 2012
2 | eclipse.preferences.version=1
3 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
4 |
--------------------------------------------------------------------------------
/plugin/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Bundle-ManifestVersion: 2
3 | Bundle-Name: j2c
4 | Bundle-SymbolicName: se.arnetheduck.j2c;singleton:=true
5 | Bundle-Version: 0.5.0.qualifier
6 | Bundle-Activator: se.arnetheduck.j2c.Activator
7 | Require-Bundle: org.eclipse.ui,
8 | org.eclipse.core.runtime,
9 | org.eclipse.jdt.core,
10 | org.eclipse.core.resources
11 | Bundle-ActivationPolicy: lazy
12 | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
13 | Export-Package: se.arnetheduck.j2c;uses:="org.eclipse.jface.resource,org.eclipse.ui.plugin,org.osgi.framework",
14 | se.arnetheduck.j2c.handlers;uses:="org.eclipse.jdt.core,org.eclipse.core.commands",
15 | se.arnetheduck.j2c.resources,
16 | se.arnetheduck.j2c.snippets;uses:="org.eclipse.jdt.core.dom,se.arnetheduck.j2c.transform",
17 | se.arnetheduck.j2c.transform;uses:="org.eclipse.jdt.core.dom,org.eclipse.core.runtime,org.eclipse.jdt.core"
18 |
--------------------------------------------------------------------------------
/plugin/build.properties:
--------------------------------------------------------------------------------
1 | source.. = src/
2 | output.. = bin/
3 | bin.includes = plugin.xml,\
4 | META-INF/,\
5 | .,\
6 | icons/
7 |
--------------------------------------------------------------------------------
/plugin/icons/sample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/arnetheduck/j2c/8ab2e2f7def06a80a4275d773bb09175426ba21a/plugin/icons/sample.gif
--------------------------------------------------------------------------------
/plugin/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
10 |
11 |
16 |
17 |
22 |
23 |
24 |
26 |
27 |
29 |
30 |
32 |
34 |
36 |
41 |
42 |
43 |
44 |
47 |
51 |
52 |
53 |
56 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/Activator.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c;
2 |
3 | import org.eclipse.jface.resource.ImageDescriptor;
4 | import org.eclipse.ui.plugin.AbstractUIPlugin;
5 | import org.osgi.framework.BundleContext;
6 |
7 | /**
8 | * The activator class controls the plug-in life cycle
9 | */
10 | public class Activator extends AbstractUIPlugin {
11 |
12 | // The plug-in ID
13 | public static final String PLUGIN_ID = "se.arnetheduck.j2c"; //$NON-NLS-1$
14 |
15 | // The shared instance
16 | private static Activator plugin;
17 |
18 | /**
19 | * The constructor
20 | */
21 | public Activator() {
22 | }
23 |
24 | /*
25 | * (non-Javadoc)
26 | *
27 | * @see
28 | * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
29 | * )
30 | */
31 | public void start(BundleContext context) throws Exception {
32 | super.start(context);
33 | plugin = this;
34 | }
35 |
36 | /*
37 | * (non-Javadoc)
38 | *
39 | * @see
40 | * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
41 | * )
42 | */
43 | public void stop(BundleContext context) throws Exception {
44 | plugin = null;
45 | super.stop(context);
46 | }
47 |
48 | /**
49 | * Returns the shared instance
50 | *
51 | * @return the shared instance
52 | */
53 | public static Activator getDefault() {
54 | return plugin;
55 | }
56 |
57 | /**
58 | * Returns an image descriptor for the image file at the given plug-in
59 | * relative path
60 | *
61 | * @param path
62 | * the path
63 | * @return the image descriptor
64 | */
65 | public static ImageDescriptor getImageDescriptor(String path) {
66 | return imageDescriptorFromPlugin(PLUGIN_ID, path);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/handlers/HandlerHelper.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.handlers;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Collection;
6 | import java.util.List;
7 |
8 | import org.eclipse.core.runtime.IPath;
9 | import org.eclipse.core.runtime.IProgressMonitor;
10 | import org.eclipse.core.runtime.IStatus;
11 | import org.eclipse.core.runtime.Status;
12 | import org.eclipse.core.runtime.jobs.Job;
13 | import org.eclipse.jdt.core.ICompilationUnit;
14 | import org.eclipse.jdt.core.IJavaElement;
15 | import org.eclipse.jdt.core.IJavaProject;
16 | import org.eclipse.jdt.core.IPackageFragment;
17 | import org.eclipse.jdt.core.IPackageFragmentRoot;
18 | import org.eclipse.jdt.core.JavaModelException;
19 | import org.eclipse.jface.dialogs.MessageDialog;
20 | import org.eclipse.ui.handlers.HandlerUtil;
21 |
22 | import se.arnetheduck.j2c.transform.Transformer;
23 |
24 | public class HandlerHelper {
25 | public static Collection units(IJavaProject project)
26 | throws JavaModelException {
27 | List units = new ArrayList();
28 | IPackageFragment[] packages = project.getPackageFragments();
29 | for (IPackageFragment pf : packages) {
30 | add(units, pf);
31 | }
32 |
33 | return units;
34 | }
35 |
36 | public static Collection units(IPackageFragmentRoot pfr)
37 | throws JavaModelException {
38 | List units = new ArrayList();
39 | for (IJavaElement pf : pfr.getChildren()) {
40 | if (pf instanceof IPackageFragment) {
41 | add(units, (IPackageFragment) pf);
42 | }
43 | }
44 |
45 | return units;
46 | }
47 |
48 | public static Collection units(IPackageFragment pf)
49 | throws JavaModelException {
50 | List units = new ArrayList();
51 | add(units, pf);
52 | return units;
53 | }
54 |
55 | public static Collection units(ICompilationUnit unit) {
56 | List units = new ArrayList();
57 |
58 | if (unit != null) {
59 | units.add(unit);
60 | }
61 |
62 | return units;
63 | }
64 |
65 | private static void add(Collection units,
66 | IPackageFragment pf) throws JavaModelException {
67 | if (pf.getKind() == IPackageFragmentRoot.K_SOURCE) {
68 | add(units, pf.getCompilationUnits());
69 | }
70 | }
71 |
72 | private static void add(Collection units,
73 | ICompilationUnit... u) {
74 | units.addAll(Arrays.asList(u));
75 | }
76 |
77 | public static void process(final IJavaProject project,
78 | final Collection units) {
79 | if (units.isEmpty()) {
80 | MessageDialog.openInformation(HandlerUtil.getActiveShell(null),
81 | "No sources", "No Java source code found in selection");
82 | return;
83 | }
84 |
85 | // We will write to the source folder prefixed with "c"
86 | final IPath p = project.getProject().getLocation()
87 | .removeLastSegments(1)
88 | .append("c" + project.getProject().getLocation().lastSegment())
89 | .addTrailingSeparator();
90 |
91 | if (!p.toFile().exists()) {
92 | MessageDialog.openError(null, "Output directory missing", p
93 | .toFile().getAbsolutePath()
94 | + " does not exist, create it before running plugin.!");
95 | } else {
96 | Job job = new Job("C++ translation") {
97 | @Override
98 | protected IStatus run(IProgressMonitor monitor) {
99 | // Set total number of work units
100 | monitor.beginTask("Translating to C++",
101 | IProgressMonitor.UNKNOWN);
102 | try {
103 | Transformer t = new Transformer(project, project
104 | .getProject().getName(), p);
105 |
106 | t.process(monitor,
107 | units.toArray(new ICompilationUnit[0]));
108 | } catch (Exception e) {
109 | e.printStackTrace();
110 | return Status.CANCEL_STATUS;
111 | }
112 |
113 | return Status.OK_STATUS;
114 | }
115 | };
116 |
117 | job.setPriority(Job.BUILD);
118 | job.schedule();
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/handlers/TestHandler.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.handlers;
2 |
3 | import java.util.Collection;
4 |
5 | import org.eclipse.core.commands.AbstractHandler;
6 | import org.eclipse.core.commands.ExecutionEvent;
7 | import org.eclipse.core.commands.ExecutionException;
8 | import org.eclipse.core.resources.IProject;
9 | import org.eclipse.core.resources.IWorkspace;
10 | import org.eclipse.core.resources.IWorkspaceRoot;
11 | import org.eclipse.core.resources.ResourcesPlugin;
12 | import org.eclipse.jdt.core.ICompilationUnit;
13 | import org.eclipse.jdt.core.IJavaProject;
14 | import org.eclipse.jdt.core.JavaCore;
15 |
16 | public class TestHandler extends AbstractHandler {
17 |
18 | @Override
19 | public Object execute(ExecutionEvent event) throws ExecutionException {
20 | IWorkspace workspace = ResourcesPlugin.getWorkspace();
21 | IWorkspaceRoot root = workspace.getRoot();
22 | // Get all projects in the workspace
23 | IProject[] projects = root.getProjects();
24 | // Loop over all projects
25 | for (IProject project : projects) {
26 | try {
27 | if (!project.isOpen()
28 | || !project.isNatureEnabled(JavaCore.NATURE_ID)) {
29 | continue;
30 | }
31 |
32 | if (!project.getName().endsWith("j2c.test")) {
33 | continue;
34 | }
35 |
36 | IJavaProject jp = JavaCore.create(project);
37 | Collection units = HandlerHelper.units(jp);
38 | HandlerHelper.process(jp, units);
39 | } catch (Exception e) {
40 | e.printStackTrace();
41 | }
42 | }
43 | return null;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/handlers/TransformHandler.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.handlers;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.Iterator;
6 |
7 | import org.eclipse.core.commands.AbstractHandler;
8 | import org.eclipse.core.commands.ExecutionEvent;
9 | import org.eclipse.core.commands.ExecutionException;
10 | import org.eclipse.core.resources.IProject;
11 | import org.eclipse.jdt.core.ICompilationUnit;
12 | import org.eclipse.jdt.core.IJavaProject;
13 | import org.eclipse.jdt.core.IPackageFragment;
14 | import org.eclipse.jdt.core.IPackageFragmentRoot;
15 | import org.eclipse.jdt.core.JavaCore;
16 | import org.eclipse.jface.dialogs.MessageDialog;
17 | import org.eclipse.jface.viewers.IStructuredSelection;
18 | import org.eclipse.ui.handlers.HandlerUtil;
19 |
20 | public class TransformHandler extends AbstractHandler {
21 | public TransformHandler() {
22 | }
23 |
24 | @Override
25 | public Object execute(ExecutionEvent event) throws ExecutionException {
26 | try {
27 | IStructuredSelection selection = (IStructuredSelection) HandlerUtil
28 | .getActiveMenuSelection(event);
29 |
30 | Collection units = new ArrayList();
31 | IJavaProject project = null;
32 |
33 | Iterator iter = selection.iterator();
34 | while (iter.hasNext()) {
35 | Object element = iter.next();
36 |
37 | if (element instanceof IJavaProject) {
38 | project = (IJavaProject) element;
39 | units.addAll(HandlerHelper.units(project));
40 | } else if (element instanceof IPackageFragmentRoot) {
41 | IPackageFragmentRoot pfr = (IPackageFragmentRoot) element;
42 | project = pfr.getJavaProject();
43 | units.addAll(HandlerHelper.units(pfr));
44 | } else if (element instanceof IPackageFragment) {
45 | IPackageFragment pf = (IPackageFragment) element;
46 | project = pf.getJavaProject();
47 | units.addAll(HandlerHelper.units(pf));
48 | } else if (element instanceof ICompilationUnit) {
49 | ICompilationUnit cu = (ICompilationUnit) element;
50 | project = cu.getJavaProject();
51 | units.addAll(HandlerHelper.units(cu));
52 | } else if (element instanceof IProject) {
53 | IProject p = (IProject) element;
54 | if (p.isOpen() && p.hasNature(JavaCore.NATURE_ID)) {
55 | project = JavaCore.create(p);
56 | units.addAll(HandlerHelper.units(project));
57 | }
58 | }
59 | }
60 |
61 | if (project != null && units != null) {
62 | HandlerHelper.process(project, units);
63 | } else {
64 | MessageDialog.openInformation(
65 | HandlerUtil.getActiveShell(event), "Invalid selection",
66 | "Please select a Java project, package or source file");
67 | }
68 | } catch (Exception e) {
69 | e.printStackTrace();
70 | MessageDialog.openError(HandlerUtil.getActiveShell(event),
71 | "Error processing selection", e.getMessage());
72 | }
73 |
74 | return null;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/Array.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | extern java::lang::Class *class_(const char16_t *c, int n);
11 |
12 | template
13 | class Array
14 | : public virtual ::java::lang::Object
15 | , public ::java::lang::Cloneable
16 | , public ::java::io::Serializable
17 | {
18 | public:
19 | static ::java::lang::Class *class_();
20 |
21 | typedef T value_type;
22 | typedef value_type *pointer_type;
23 | typedef pointer_type iterator;
24 | typedef const value_type *const_pointer_type;
25 | typedef const_pointer_type const_iterator;
26 |
27 | typedef int size_type;
28 |
29 | Array() : length(0), p(nullptr) { }
30 | Array(int n) : length(n), p(n == 0 ? nullptr : new value_type[n])
31 | {
32 | for(auto x = p; x != p + length; ++x) *x = value_type();
33 | }
34 |
35 | Array(const value_type *values, int n) : length(n), p(new value_type[n])
36 | {
37 | auto x = p;
38 | for(auto v = values; v != values + n; ++v) *x++ = *v;
39 | }
40 |
41 | template
42 | Array(std::initializer_list l) : length(l.size()), p(new value_type[l.size()])
43 | {
44 | auto x = p;
45 | for(auto v : l) *x++ = v;
46 | }
47 |
48 | Array(const Array &rhs) : Array(rhs.p, rhs.length) { }
49 |
50 | Array(Array &&rhs) : length(rhs.length), p(rhs.p)
51 | {
52 | const_cast(rhs.p) = 0;
53 | }
54 |
55 | Array &operator=(const Array &rhs)
56 | {
57 | if(&rhs != this) {
58 | if(length != rhs.length) {
59 | delete p;
60 | const_cast(p) = 0;
61 | const_cast(length) = rhs.length;
62 | const_cast(p) = new value_type[length];
63 | }
64 |
65 | auto x = p;
66 | for(auto v = rhs.p; v != rhs.p + rhs.length; ++v) *x++ = *v;
67 | }
68 |
69 | return *this;
70 | }
71 |
72 | Array &operator=(Array &&rhs)
73 | {
74 | if(&rhs != this) {
75 | delete p;
76 | const_cast(length) = rhs.length;
77 | const_cast(p) = rhs.p;
78 | const_cast(rhs.p) = 0;
79 | }
80 |
81 | return *this;
82 | }
83 |
84 | virtual ~Array() { delete p; }
85 |
86 | Array* clone() override { return new Array(*this); }
87 |
88 | value_type operator[](size_type i) const { return p[i]; }
89 | value_type &operator[](size_type i) { return p[i]; }
90 |
91 | value_type get(size_type i) const { return p[i]; }
92 | value_type &set(size_type i, value_type x) { return (p[i] = x); }
93 |
94 | iterator begin() { return p; }
95 | const_iterator begin() const { return p; }
96 | const_iterator cbegin() const { return begin(); }
97 |
98 | iterator end() { return p + length; }
99 | const_iterator end() const { return p + length; }
100 | const_iterator cend() const { return end(); }
101 |
102 | const size_type length;
103 | const pointer_type p;
104 |
105 | private:
106 | ::java::lang::Class *getClass0() override { return class_(); }
107 | };
108 |
109 | typedef Array boolArray;
110 | typedef Array char16_tArray;
111 | typedef Array int8_tArray;
112 | typedef Array int16_tArray;
113 | typedef Array int32_tArray;
114 | typedef Array int64_tArray;
115 | typedef Array doubleArray;
116 | typedef Array floatArray;
117 |
118 | template<>
119 | inline java::lang::Class* boolArray::class_() {
120 | static ::java::lang::Class* c = ::class_(u"boolean[]", 9);
121 | return c;
122 | }
123 | template<>
124 | inline java::lang::Class* char16_tArray::class_() {
125 | static ::java::lang::Class* c = ::class_(u"char[]", 9);
126 | return c;
127 | }
128 | template<>
129 | inline java::lang::Class* int8_tArray::class_() {
130 | static ::java::lang::Class* c = ::class_(u"byte[]", 9);
131 | return c;
132 | }
133 | template<>
134 | inline java::lang::Class* int16_tArray::class_() {
135 | static ::java::lang::Class* c = ::class_(u"short[]", 9);
136 | return c;
137 | }
138 | template<>
139 | inline java::lang::Class* int32_tArray::class_() {
140 | static ::java::lang::Class* c = ::class_(u"int[]", 9);
141 | return c;
142 | }
143 | template<>
144 | inline java::lang::Class* int64_tArray::class_() {
145 | static ::java::lang::Class* c = ::class_(u"long[]", 9);
146 | return c;
147 | }
148 | template<>
149 | inline java::lang::Class* doubleArray::class_() {
150 | static ::java::lang::Class* c = ::class_(u"double[]", 9);
151 | return c;
152 | }
153 | template<>
154 | inline java::lang::Class* floatArray::class_() {
155 | static ::java::lang::Class* c = ::class_(u"float[]", 9);
156 | return c;
157 | }
158 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/Main.cpp.tmpl:
--------------------------------------------------------------------------------
1 | %1$s
2 |
3 | extern void init_jvm();
4 | extern java::lang::StringArray* make_args(int args, char** argv);
5 |
6 | int main(int argc, char** argv)
7 | {
8 | init_jvm();
9 |
10 | %2$s::main(make_args(argc, argv));
11 |
12 | return 0;
13 | }
14 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/Makefile.tmpl:
--------------------------------------------------------------------------------
1 | INCLUDES := $(INCLUDES) -Isrc -Iext/src
2 | EXTRA_LIBS ?= -l$(NAME)-ext
3 |
4 | CPPFLAGS := $(CPPFLAGS) $(INCLUDES)
5 | CFLAGS := $(CFLAGS) -g -pipe -MMD -MP
6 | CXXFLAGS := $(CFLAGS) -std=gnu++11
7 |
8 | BIN := bin
9 | OBJ := obj
10 |
11 | NAME := %1$s
12 |
13 | LIB = lib$(NAME).a
14 | EXT_LIB = lib$(NAME)-ext.a
15 |
16 | LIBS = $(BIN)/$(LIB) $(BIN)/$(EXT_LIB)
17 |
18 | SRC = src
19 | STUB = stub
20 | NATIVE = native
21 |
22 | SRCS = \
23 | %2$s
24 |
25 | STUB_SRCS = \
26 | %3$s
27 |
28 | NATIVE_SRCS = \
29 | %4$s
30 |
31 | EXT_SRCS = \
32 | %5$s
33 |
34 | EXT_STUB_SRCS = \
35 | %6$s
36 |
37 | EXT_NATIVE_SRCS = \
38 | %7$s
39 |
40 | MAIN_SRCS = \
41 | %8$s
42 |
43 | MAINS = $(MAIN_SRCS:$(SRC)/%%-main.cpp=$(BIN)/%%)
44 | OBJS = $(SRCS:$(SRC)/%%.cpp=$(OBJ)/%%.o)
45 | STUB_OBJS = $(STUB_SRCS:$(STUB)/%%.cpp=$(OBJ)/%%.o)
46 | NATIVE_OBJS = $(NATIVE_SRCS:$(NATIVE)/%%.cpp=$(OBJ)/%%.o)
47 |
48 | EXT_OBJS = $(EXT_SRCS:ext/$(SRC)/%%.cpp=$(OBJ)/%%.o)
49 | EXT_STUB_OBJS = $(EXT_STUB_SRCS:ext/$(STUB)/%%.cpp=$(OBJ)/%%.o)
50 | EXT_NATIVE_OBJS = $(EXT_NATIVE_SRCS:ext/$(NATIVE)/%%.cpp=$(OBJ)/%%.o)
51 |
52 | all: $(LIBS)
53 |
54 | define cc-command
55 | @mkdir -p $(dir $@);
56 | @echo Compile $<; $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
57 | endef
58 |
59 | $(OBJS):$(OBJ)/%%.o: $(SRC)/%%.cpp | print-opts
60 | $(cc-command)
61 |
62 | $(STUB_OBJS):$(OBJ)/%%.o: $(STUB)/%%.cpp | print-opts
63 | $(cc-command)
64 |
65 | $(NATIVE_OBJS):$(OBJ)/%%.o: $(NATIVE)/%%.cpp | print-opts
66 | $(cc-command)
67 |
68 | $(EXT_OBJS):$(OBJ)/%%.o: ext/$(SRC)/%%.cpp | print-opts
69 | $(cc-command)
70 |
71 | $(EXT_STUB_OBJS):$(OBJ)/%%.o: ext/$(STUB)/%%.cpp | print-opts
72 | $(cc-command)
73 |
74 | $(EXT_NATIVE_OBJS):$(OBJ)/%%.o: ext/$(NATIVE)/%%.cpp | print-opts
75 | $(cc-command)
76 |
77 | %%.a:
78 | @echo Archive $@
79 | @mkdir -p $(dir $@)
80 | @rm -f $@
81 | @ar rcs $@ $^
82 |
83 | $(BIN)/$(LIB): $(OBJS) $(STUB_OBJS) $(NATIVE_OBJS)
84 |
85 | $(BIN)/$(EXT_LIB): $(EXT_OBJS) $(EXT_STUB_OBJS) $(EXT_NATIVE_OBJS)
86 |
87 | $(MAINS):$(BIN)/%%:$(SRC)/%%-main.cpp $(LIBS)
88 | @mkdir -p $(dir $@);
89 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -L$(BIN) -o $@ $< -l$(NAME) $(EXTRA_LIBS)
90 |
91 | mains: $(MAINS)
92 |
93 | clean:
94 | rm -rf $(OBJ) $(BIN)
95 |
96 | print-opts:
97 | @echo Building with \"$(CXX) $(CPPFLAGS) $(CXXFLAGS)\"
98 |
99 | .PHONY: all mains clean print-opts
100 |
101 | -include $(OBJS:%%.o=%%.d)
102 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/ObjectArray.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | namespace java
11 | {
12 | namespace lang
13 | {
14 | class ObjectArray;
15 | }
16 | }
17 |
18 | extern java::lang::Class *class_(const char16_t *c, int n);
19 |
20 | class java::lang::ObjectArray
21 | : public virtual ::java::lang::Object
22 | , public virtual ::java::lang::Cloneable
23 | , public virtual ::java::io::Serializable
24 | {
25 | public:
26 | static ::java::lang::Class *class_() {
27 | static ::java::lang::Class* c = ::class_(u"java.lang.Object[]", 31);
28 | return c;
29 | }
30 |
31 | typedef ::java::lang::Object super;
32 |
33 | typedef Object *value_type;
34 | typedef value_type *pointer_type;
35 | typedef pointer_type iterator;
36 | typedef const value_type *const_pointer_type;
37 | typedef const_pointer_type const_iterator;
38 |
39 | typedef int size_type;
40 |
41 | ObjectArray() : length(0), p(nullptr) { }
42 | ObjectArray(int n) : length(n), p(n == 0 ? nullptr : new value_type[n])
43 | {
44 | for(auto x = p; x != p + length; ++x) *x = value_type();
45 | }
46 |
47 | ObjectArray(const value_type *values, int n) : length(n), p(new value_type[n])
48 | {
49 | auto x = p;
50 | for(auto v = values; v != values + n; ++v) *x++ = *v;
51 | }
52 |
53 | template
54 | ObjectArray(std::initializer_list l) : length(l.size()), p(new value_type[l.size()])
55 | {
56 | auto x = p;
57 | for(auto v : l) *x++ = v;
58 | }
59 |
60 | ObjectArray(const ObjectArray &rhs) : ObjectArray(rhs.p, rhs.length)
61 | {
62 | }
63 |
64 | ObjectArray(ObjectArray &&rhs) : length(rhs.length), p(rhs.p)
65 | {
66 | const_cast(rhs.p) = 0;
67 | }
68 |
69 | ObjectArray &operator=(const ObjectArray &rhs)
70 | {
71 | if(&rhs != this) {
72 | if(length != rhs.length) {
73 | delete p;
74 | const_cast(p) = 0;
75 | const_cast(length) = rhs.length;
76 | const_cast(p) = new value_type[length];
77 | }
78 |
79 | auto x = p;
80 | for(auto v = rhs.p; v != rhs.p + rhs.length; ++v) *x++ = *v;
81 | }
82 |
83 | return *this;
84 | }
85 |
86 | ObjectArray &operator=(ObjectArray &&rhs)
87 | {
88 | if(&rhs != this) {
89 | delete p;
90 | const_cast(length) = rhs.length;
91 | const_cast(p) = rhs.p;
92 | const_cast(rhs.p) = 0;
93 | }
94 |
95 | return *this;
96 | }
97 |
98 | virtual ~ObjectArray() { delete p; }
99 |
100 | ObjectArray* clone() override { return new ObjectArray(*this); }
101 |
102 | value_type operator[](size_type i) const { return get(i); }
103 | value_type get(size_type i) const { return p[i]; }
104 |
105 | template
106 | T set(size_type i, T x) { set0(i, x); return x; }
107 |
108 | iterator begin() { return p; }
109 | const_iterator begin() const { return p; }
110 | const_iterator cbegin() const { return begin(); }
111 |
112 | iterator end() { return p + length; }
113 | const_iterator end() const { return p + length; }
114 | const_iterator cend() const { return end(); }
115 |
116 | const size_type length;
117 | const pointer_type p;
118 |
119 | private:
120 | ::java::lang::Class *getClass0() override { return class_(); }
121 |
122 | virtual void set0(size_type i, Object *x) { p[i] = x; }
123 | };
124 |
125 | template
126 | ArrayType* __newMultiArray(int dim) {
127 | return new ArrayType(dim);
128 | }
129 |
130 | template
131 | ArrayType* __newMultiArray(int dim, Dims... dims) {
132 | auto ret = new ArrayType(dim);
133 | for (auto i = 0; i < dim; ++i) {
134 | ret->p[i] = __newMultiArray::type>(dims...);
135 | }
136 | return ret;
137 | }
138 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/SubArray.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | template
10 | struct SubArray : public virtual Bases... {
11 | static ::java::lang::Class *class_() {
12 | static ::java::lang::Class* c = ::class_(u"TODO[]", 31);
13 | return c;
14 | }
15 |
16 | typedef ComponentType* value_type;
17 | typedef int size_type;
18 |
19 | struct iterator {
20 | typedef SubArray::value_type value_type;
21 | typedef std::ptrdiff_t difference_type;
22 | typedef value_type* pointer;
23 | typedef value_type reference; // Good enough for input iterator
24 | typedef std::input_iterator_tag iterator_category;
25 |
26 | iterator() : p() {}
27 | explicit iterator(::java::lang::Object** p) : p(p) {}
28 |
29 | pointer operator->() { return &dynamic_cast(*p); }
30 | reference operator*() { return dynamic_cast(*p); }
31 |
32 | iterator& operator++() { ++p; return *this; }
33 | iterator operator++(int) { iterator tmp(p); ++*this; return tmp; }
34 | iterator& operator--() { --p; return *this; }
35 | iterator operator--(int) { iterator tmp(p); --*this; return tmp; }
36 |
37 | bool operator==(iterator rhs) { return p == rhs.p; }
38 | bool operator!=(iterator rhs) { return !(*this == rhs); }
39 |
40 | ::java::lang::Object** p;
41 | };
42 |
43 | SubArray() { }
44 | SubArray(int n) : ::java::lang::ObjectArray(n) { }
45 |
46 | SubArray(const value_type *values, int n) : ::java::lang::ObjectArray(n)
47 | {
48 | auto x = this->p;
49 | for(auto v = values; v != values + n; ++v) *x++ = *v;
50 | }
51 |
52 | template
53 | SubArray(std::initializer_list l) : ::java::lang::ObjectArray(l.size())
54 | {
55 | auto x = this->p;
56 | for(auto v : l) *x++ = v;
57 | }
58 |
59 | SubArray(const SubArray &rhs) : ::java::lang::ObjectArray(rhs) { }
60 | SubArray(SubArray &&rhs) : ::java::lang::ObjectArray(std::move(rhs)) { }
61 | virtual ~SubArray() {}
62 |
63 | SubArray &operator=(const SubArray &rhs)
64 | {
65 | ::java::lang::ObjectArray::operator=(rhs);
66 | return *this;
67 | }
68 |
69 | SubArray &operator=(SubArray &&rhs)
70 | {
71 | ::java::lang::ObjectArray::operator=(std::move(rhs));
72 | return *this;
73 | }
74 |
75 | SubArray* clone() override { return new SubArray(*this); }
76 |
77 | value_type operator[](size_type i) const { return get(i); }
78 | value_type get(size_type i) const { return dynamic_cast(this->p[i]); }
79 |
80 | iterator begin() { return iterator(this->p); }
81 | iterator end() { return iterator(this->p + this->length); }
82 |
83 | private:
84 | ::java::lang::Class *getClass0() override { return class_(); }
85 |
86 | void set0(size_type i, ::java::lang::Object *x) override
87 | {
88 | if(x && !dynamic_cast(x)) {
89 | throw new ::java::lang::ArrayStoreException();
90 | }
91 |
92 | this->p[i] = x;
93 | }
94 | };
95 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/finally.hpp:
--------------------------------------------------------------------------------
1 | namespace
2 | {
3 | template
4 | struct finally_
5 | {
6 | finally_(F f) : f(f), moved(false) { }
7 | finally_(finally_ &&x) : f(x.f), moved(false) { x.moved = true; }
8 | ~finally_() { if(!moved) f(); }
9 | private:
10 | finally_(const finally_&); finally_& operator=(const finally_&);
11 | F f;
12 | bool moved;
13 | };
14 |
15 | template finally_ finally(F f) { return finally_(f); }
16 | }
17 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/java_cast.hpp:
--------------------------------------------------------------------------------
1 | template
2 | static T java_cast(U* u)
3 | {
4 | if(!u) return static_cast(nullptr);
5 | auto t = dynamic_cast(u);
6 | if(!t) throw new ::java::lang::ClassCastException();
7 | return t;
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/npc.hpp:
--------------------------------------------------------------------------------
1 | template
2 | static T* npc(T* t)
3 | {
4 | if(!t) throw new ::java::lang::NullPointerException();
5 | return t;
6 | }
7 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/resources/synchronized.hpp:
--------------------------------------------------------------------------------
1 | extern void lock(::java::lang::Object *);
2 | extern void unlock(::java::lang::Object *);
3 |
4 | namespace
5 | {
6 | struct synchronized
7 | {
8 | synchronized(::java::lang::Object *o) : o(o) { ::lock(o); }
9 | ~synchronized() { ::unlock(o); }
10 | private:
11 | synchronized(const synchronized&); synchronized& operator=(const synchronized&);
12 | ::java::lang::Object *o;
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/snippets/GetSetSnippet.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.snippets;
2 |
3 | import org.eclipse.jdt.core.dom.IMethodBinding;
4 | import org.eclipse.jdt.core.dom.ITypeBinding;
5 | import org.eclipse.jdt.core.dom.IVariableBinding;
6 |
7 | import se.arnetheduck.j2c.transform.CName;
8 | import se.arnetheduck.j2c.transform.EmptySnippet;
9 | import se.arnetheduck.j2c.transform.StubWriter;
10 | import se.arnetheduck.j2c.transform.TransformUtil;
11 | import se.arnetheduck.j2c.transform.Transformer;
12 |
13 | public class GetSetSnippet extends EmptySnippet {
14 |
15 | @Override
16 | public boolean body(Transformer ctx, StubWriter w, IMethodBinding mb) {
17 | String name = mb.getName();
18 | if (name.length() < 4)
19 | return true;
20 |
21 | boolean getter = name.startsWith("get");
22 | boolean setter = name.startsWith("set");
23 | if (!getter && !setter)
24 | return true;
25 |
26 | char[] vname = name.substring(3).toCharArray();
27 | vname[0] = Character.toLowerCase(vname[0]);
28 | ITypeBinding tb = mb.getDeclaringClass();
29 | if (tb == null)
30 | return true;
31 |
32 | String v = new String(vname);
33 | boolean ms = TransformUtil.isStatic(mb);
34 |
35 | for (IVariableBinding vb : tb.getDeclaredFields()) {
36 | if (ms == TransformUtil.isStatic(vb) && vb.getName().equals(v)) {
37 | boolean asMethod = TransformUtil.asMethod(vb);
38 | if (getter
39 | && mb.getReturnType().isAssignmentCompatible(
40 | vb.getType())) {
41 | w.println("return " + CName.of(vb) + (asMethod ? "()" : "")
42 | + " ; /* getter */");
43 | } else if (setter
44 | && mb.getReturnType().getName().equals("void")
45 | && mb.getParameterTypes().length == 1
46 | && vb.getType().isAssignmentCompatible(
47 | mb.getParameterTypes()[0])) {
48 | w.print(TransformUtil.indent(1));
49 | if (ms) {
50 | w.print(CName.of(tb) + "::");
51 | } else {
52 | w.print("this->");
53 | }
54 |
55 | w.println(CName.of(vb) + (asMethod ? "()" : "") + " = "
56 | + TransformUtil.paramName(mb, 0) + "; /* setter */");
57 | }
58 |
59 | return false;
60 | }
61 | }
62 |
63 | return true;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/snippets/ReplaceInvocation.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.snippets;
2 |
3 | import org.eclipse.jdt.core.dom.ASTNode;
4 | import org.eclipse.jdt.core.dom.IMethodBinding;
5 | import org.eclipse.jdt.core.dom.ITypeBinding;
6 | import org.eclipse.jdt.core.dom.MethodInvocation;
7 | import org.eclipse.jdt.core.dom.TypeLiteral;
8 |
9 | import se.arnetheduck.j2c.transform.CName;
10 | import se.arnetheduck.j2c.transform.EmptySnippet;
11 | import se.arnetheduck.j2c.transform.ImplWriter;
12 | import se.arnetheduck.j2c.transform.Transformer;
13 |
14 | public class ReplaceInvocation extends EmptySnippet {
15 |
16 | @Override
17 | public boolean node(Transformer ctx, ImplWriter w, ASTNode node) {
18 | if (node instanceof MethodInvocation) {
19 | return replace(w, (MethodInvocation) node);
20 | }
21 |
22 | return super.node(ctx, w, node);
23 | }
24 |
25 | private static boolean replace(ImplWriter w, MethodInvocation node) {
26 | if (replaceEnsureClassInitialized(w, node)) {
27 | return false;
28 | }
29 |
30 | return true;
31 | }
32 |
33 | private static boolean replaceEnsureClassInitialized(ImplWriter w,
34 | MethodInvocation node) {
35 | if (!node.getName().getIdentifier().equals("ensureClassInitialized")) {
36 | return false;
37 | }
38 |
39 | if (node.arguments().size() != 1
40 | || !(node.arguments().get(0) instanceof TypeLiteral)) {
41 | return false;
42 | }
43 |
44 | IMethodBinding mb = node.resolveMethodBinding();
45 | if (!mb.getDeclaringClass().getQualifiedName()
46 | .equals("sun.misc.Unsafe")) {
47 | return false;
48 | }
49 |
50 | TypeLiteral tl = (TypeLiteral) node.arguments().get(0);
51 | ITypeBinding tb = tl.getType().resolveBinding();
52 | w.hardDep(tb);
53 | w.print(CName.relative(tb, w.type, true) + "::clinit()");
54 |
55 | return true;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/BindingComparator.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.util.Comparator;
4 |
5 | import org.eclipse.jdt.core.dom.IBinding;
6 |
7 | public final class BindingComparator implements Comparator {
8 | @Override
9 | public int compare(IBinding o1, IBinding o2) {
10 | return o1.getKey().compareTo(o2.getKey());
11 | }
12 | }
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/DepInfo.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.PrintWriter;
4 | import java.io.Serializable;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.List;
8 | import java.util.Set;
9 | import java.util.Stack;
10 | import java.util.TreeSet;
11 |
12 | import org.eclipse.jdt.core.dom.ITypeBinding;
13 |
14 | public class DepInfo {
15 | private final Transformer ctx;
16 |
17 | private final Set hardDeps = new TreeSet(
18 | new BindingComparator());
19 | private final Set softDeps = new TreeSet(
20 | new BindingComparator());
21 |
22 | private boolean javaCast;
23 | private boolean npc;
24 | private boolean atomic;
25 |
26 | private boolean finally_;
27 |
28 | private boolean synchronized_;
29 | private boolean fmod;
30 |
31 | public DepInfo(Transformer ctx) {
32 | this.ctx = ctx;
33 | }
34 |
35 | /** Soft dependency, forward declaration sufficient */
36 | public void soft(ITypeBinding dep) {
37 | if (TransformUtil.addDep(dep, softDeps)) {
38 | ctx.softDep(dep);
39 | }
40 |
41 | checkArray(dep, false);
42 | }
43 |
44 | /** Hard dependency, class declaration required */
45 | public void hard(ITypeBinding dep) {
46 | if (TransformUtil.addDep(dep, hardDeps)) {
47 | ctx.hardDep(dep);
48 | soft(dep);
49 | }
50 |
51 | checkArray(dep, true);
52 | }
53 |
54 | private void checkArray(ITypeBinding dep, boolean hard) {
55 | if (!dep.isArray())
56 | return;
57 |
58 | ITypeBinding ct = dep.getComponentType();
59 | if (ct.isPrimitive())
60 | return;
61 |
62 | if (TransformUtil.same(ct, Object.class))
63 | return;
64 |
65 | if (hard) {
66 | hard(ct);
67 | } else {
68 | soft(ct);
69 | }
70 |
71 | List bases = arrayBases(ct);
72 | for (ITypeBinding base : bases) {
73 | if (hard) {
74 | hard(base);
75 | } else {
76 | soft(base);
77 | }
78 | }
79 |
80 | if (hard) {
81 | hard(ctx.resolve(ArrayStoreException.class));
82 | }
83 | }
84 |
85 | public Set getHardDeps() {
86 | return hardDeps;
87 | }
88 |
89 | public Set getSoftDeps() {
90 | return softDeps;
91 | }
92 |
93 | public boolean needsJavaCast() {
94 | return javaCast;
95 | }
96 |
97 | public void setJavaCast() {
98 | javaCast = true;
99 | hard(ctx.resolve(ClassCastException.class));
100 | }
101 |
102 | public boolean needsNpc() {
103 | return npc;
104 | }
105 |
106 | public void setNpc() {
107 | npc = true;
108 | hard(ctx.resolve(NullPointerException.class));
109 | }
110 |
111 | public boolean needsAtomic() {
112 | return atomic;
113 | }
114 |
115 | public void setNeedsAtomic() {
116 | atomic = true;
117 | }
118 |
119 | public boolean needsFinally() {
120 | return finally_;
121 | }
122 |
123 | public void setNeedsFinally() {
124 | finally_ = true;
125 | }
126 |
127 | public boolean needsSynchronized() {
128 | return synchronized_;
129 | }
130 |
131 | public void setNeedsSynchronized() {
132 | synchronized_ = true;
133 | }
134 |
135 | public boolean needsFmod() {
136 | return fmod;
137 | }
138 |
139 | public void setNeedsFmod() {
140 | fmod = true;
141 | }
142 |
143 | public void printArrays(PrintWriter out) {
144 | Set done = new TreeSet(
145 | new BindingComparator());
146 |
147 | boolean printed = false;
148 | Stack cur = new Stack();
149 | for (ITypeBinding dep : softDeps) {
150 | printed |= printArray(out, dep, done, cur);
151 | }
152 |
153 | TransformUtil.setNs(out, new ArrayList(), cur);
154 | if (printed) {
155 | out.println();
156 | }
157 | }
158 |
159 | private boolean printArray(PrintWriter out, ITypeBinding dep,
160 | Set done, Stack cur) {
161 | dep = dep.getErasure();
162 |
163 | if (done.contains(dep))
164 | return false;
165 |
166 | if (!dep.isArray())
167 | return false;
168 |
169 | ITypeBinding ct = dep.getComponentType();
170 | if (ct.isPrimitive() || TransformUtil.same(ct, Object.class))
171 | return false;
172 |
173 | printArray(out, ct, done, cur);
174 |
175 | List bases = arrayBases(ct);
176 | for (ITypeBinding base : bases) {
177 | printArray(out, base, done, cur);
178 | }
179 |
180 | if (done.isEmpty()) {
181 | out.print("template struct SubArray;");
182 | }
183 |
184 | TransformUtil.setNs(out,
185 | Arrays.asList(CName.packageOf(ct).split("\\.")), cur);
186 |
187 | out.print("typedef ::SubArray< " + CName.qualified(ct, true));
188 |
189 | for (ITypeBinding base : bases) {
190 | out.print(", " + CName.relative(base, ct, true));
191 | }
192 |
193 | out.println(" > " + CName.of(dep) + ";");
194 |
195 | done.add(dep);
196 |
197 | return true;
198 | }
199 |
200 | private List arrayBases(ITypeBinding ct) {
201 | List ret = new ArrayList();
202 | if (ct.isArray()) {
203 | ret.add(ctx.resolve(Cloneable.class).createArrayType(1));
204 | ret.add(ctx.resolve(Serializable.class).createArrayType(1));
205 | return ret;
206 | }
207 |
208 | if (ct.getSuperclass() == null) {
209 | ret.add(ctx.resolve(Object.class).createArrayType(1));
210 | } else {
211 | ret.add(ct.getSuperclass().createArrayType(1));
212 | }
213 |
214 | for (ITypeBinding cti : ct.getInterfaces()) {
215 | ret.add(cti.createArrayType(1));
216 | }
217 |
218 | return ret;
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/EmptySnippet.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import org.eclipse.jdt.core.dom.ASTNode;
4 | import org.eclipse.jdt.core.dom.IMethodBinding;
5 | import org.eclipse.jdt.core.dom.ITypeBinding;
6 | import org.eclipse.jdt.core.dom.IVariableBinding;
7 |
8 | public class EmptySnippet implements Snippet {
9 | @Override
10 | public boolean node(Transformer ctx, HeaderWriter w, ASTNode node) {
11 | return true;
12 | }
13 |
14 | @Override
15 | public boolean node(Transformer ctx, ImplWriter w, ASTNode node) {
16 | return true;
17 | }
18 |
19 | @Override
20 | public boolean type(Transformer ctx, TypeBindingHeaderWriter w,
21 | ITypeBinding tb) {
22 | return true;
23 | }
24 |
25 | @Override
26 | public boolean field(Transformer ctx, TypeBindingHeaderWriter w,
27 | IVariableBinding vb) {
28 | return true;
29 | }
30 |
31 | @Override
32 | public boolean method(Transformer ctx, TypeBindingHeaderWriter w,
33 | IMethodBinding mb) {
34 | return true;
35 | }
36 |
37 | @Override
38 | public boolean prefix(Transformer ctx, StubWriter w, boolean natives) {
39 | return true;
40 | }
41 |
42 | @Override
43 | public boolean suffix(Transformer ctx, StubWriter w, boolean natives) {
44 | return true;
45 | }
46 |
47 | @Override
48 | public boolean field(Transformer ctx, StubWriter w, IVariableBinding vb) {
49 | return true;
50 | }
51 |
52 | @Override
53 | public boolean method(Transformer ctx, StubWriter w, IMethodBinding mb) {
54 | return true;
55 | }
56 |
57 | @Override
58 | public boolean body(Transformer ctx, StubWriter w, IMethodBinding mb) {
59 | return true;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/FileUtil.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 | import java.io.PrintWriter;
11 | import java.util.Scanner;
12 |
13 | public class FileUtil {
14 | public static void copy(File source, File target) throws IOException {
15 | InputStream is = null;
16 | OutputStream os = null;
17 | byte[] buf = new byte[4096];
18 | try {
19 | is = new FileInputStream(source);
20 | try {
21 | os = new FileOutputStream(target);
22 | for (int n = is.read(buf); n != -1; n = is.read(buf)) {
23 | os.write(buf, 0, n);
24 | }
25 | } finally {
26 | is.close();
27 | }
28 | } finally {
29 | if (os != null) {
30 | os.close();
31 | }
32 | }
33 | }
34 |
35 | public static String readResource(String resource) {
36 | InputStream is = null;
37 | try {
38 | is = FileUtil.class.getResourceAsStream(resource);
39 | return FileUtil.read(is);
40 | } catch (Exception e) {
41 | throw new RuntimeException(e);
42 | } finally {
43 | if (is != null) {
44 | try {
45 | is.close();
46 | } catch (IOException e) {
47 | throw new RuntimeException(e);
48 | }
49 | }
50 | }
51 | }
52 |
53 | private static String read(InputStream resource) {
54 | return new Scanner(resource).useDelimiter("\\A").next();
55 | }
56 |
57 | public static PrintWriter open(File target) throws FileNotFoundException {
58 | if (!target.getParentFile().exists()) {
59 | target.getParentFile().mkdirs();
60 | }
61 |
62 | FileOutputStream fos = new FileOutputStream(target);
63 | return new PrintWriter(fos);
64 | }
65 |
66 | public static void writeResource(String name, File target)
67 | throws IOException {
68 | InputStream is = null;
69 | try {
70 | is = FileUtil.class.getResourceAsStream(name);
71 | writeResource(is, target);
72 | } finally {
73 | if (is != null) {
74 | is.close();
75 | }
76 | }
77 | }
78 |
79 | private static void writeResource(InputStream resource, File target)
80 | throws IOException {
81 | PrintWriter pw = null;
82 | String txt = FileUtil.read(resource);
83 |
84 | try {
85 | pw = open(target);
86 | pw.write(txt);
87 | } finally {
88 | if (pw != null) {
89 | pw.close();
90 | }
91 | }
92 | }
93 |
94 | public static void writeTemplate(String resource, File target,
95 | Object... params) throws IOException {
96 | InputStream is = null;
97 | try {
98 | is = FileUtil.class.getResourceAsStream(resource);
99 | writeTemplate(is, target, params);
100 | } finally {
101 | if (is != null) {
102 | is.close();
103 | }
104 | }
105 | }
106 |
107 | private static void writeTemplate(InputStream template, File target,
108 | Object... params) throws IOException {
109 | String format = read(template);
110 |
111 | PrintWriter pw = null;
112 | try {
113 | pw = open(target);
114 | pw.format(format, params);
115 | } finally {
116 | if (pw != null) {
117 | pw.close();
118 | }
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/ForwardWriter.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.IOException;
4 | import java.io.PrintWriter;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.Collection;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.Stack;
11 | import java.util.TreeSet;
12 |
13 | import org.eclipse.core.runtime.IPath;
14 | import org.eclipse.jdt.core.dom.ITypeBinding;
15 |
16 | public class ForwardWriter {
17 | public static class Info implements Comparable {
18 | public String packageName;
19 | public String className;
20 | public boolean isInterface;
21 | public boolean isPrimitive;
22 | public boolean isPrimitiveArray;
23 |
24 | public Info(ITypeBinding tb) {
25 | isInterface = tb.isInterface();
26 | isPrimitive = tb.isPrimitive();
27 | isPrimitiveArray = TransformUtil.isPrimitiveArray(tb);
28 |
29 | packageName = CName.packageOf(tb);
30 | className = CName.of(isPrimitiveArray ? tb.getComponentType() : tb);
31 | }
32 |
33 | @Override
34 | public int compareTo(Info o) {
35 | int c = packageName.compareTo(o.packageName);
36 | c = c == 0 ? -Boolean.valueOf(isPrimitive).compareTo(o.isPrimitive)
37 | : c;
38 | return c == 0 ? className.compareTo(o.className) : c;
39 | }
40 | }
41 |
42 | private final IPath root;
43 |
44 | private Stack cur = new Stack();
45 |
46 | private final Transformer ctx;
47 |
48 | public ForwardWriter(Transformer ctx, IPath root) {
49 | this.ctx = ctx;
50 | this.root = root;
51 | }
52 |
53 | public void write(Collection infos) throws IOException {
54 | Map> types = new HashMap>();
55 | for (Info info : infos) {
56 | TreeSet l = types.get(info.packageName);
57 | if (l == null) {
58 | types.put(info.packageName, l = new TreeSet());
59 | }
60 |
61 | l.add(info);
62 | }
63 |
64 | for (Map.Entry> e : types.entrySet()) {
65 | boolean hasArray = false;
66 | boolean hasPrimitive = false;
67 |
68 | PrintWriter pw = null;
69 | try {
70 | pw = FileUtil.open(root
71 | .append("src")
72 | .append(TransformUtil.packageHeader(ctx.getName(),
73 | e.getKey())).toFile());
74 |
75 | pw.println("// Forward declarations for " + e.getKey());
76 |
77 | pw.println("#pragma once");
78 | pw.println();
79 |
80 | TransformUtil.setNs(pw,
81 | e.getKey().length() == 0 ? new ArrayList()
82 | : Arrays.asList(e.getKey().split("\\.")), cur);
83 |
84 | String i = TransformUtil.indent(cur.size());
85 | for (Info info : e.getValue()) {
86 | if (info.isPrimitive) {
87 | if (!hasPrimitive) {
88 | pw.println("#include ");
89 | pw.println("#include ");
90 | pw.println();
91 |
92 | hasPrimitive = true;
93 | }
94 |
95 | continue;
96 | }
97 |
98 | if (info.isPrimitiveArray) {
99 | if (!hasArray) {
100 | pw.println(i + "template class Array;");
101 | hasArray = true;
102 | }
103 |
104 | pw.format("%stypedef Array<%2$s> %2$sArray;\n", i,
105 | info.className);
106 |
107 | continue;
108 | }
109 |
110 | pw.format("%s%s %s;\n", i, info.isInterface ? "struct"
111 | : "class", info.className);
112 | }
113 |
114 | TransformUtil.setNs(pw, new ArrayList(), cur);
115 | } finally {
116 | if (pw != null) {
117 | pw.close();
118 | }
119 | }
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/HeaderWriter.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.PrintWriter;
4 | import java.io.StringWriter;
5 | import java.lang.reflect.Modifier;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.Iterator;
9 | import java.util.List;
10 |
11 | import org.eclipse.core.runtime.IPath;
12 | import org.eclipse.jdt.core.dom.ASTNode;
13 | import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
14 | import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
15 | import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
16 | import org.eclipse.jdt.core.dom.Block;
17 | import org.eclipse.jdt.core.dom.BodyDeclaration;
18 | import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
19 | import org.eclipse.jdt.core.dom.EnumDeclaration;
20 | import org.eclipse.jdt.core.dom.FieldDeclaration;
21 | import org.eclipse.jdt.core.dom.IBinding;
22 | import org.eclipse.jdt.core.dom.IMethodBinding;
23 | import org.eclipse.jdt.core.dom.ITypeBinding;
24 | import org.eclipse.jdt.core.dom.IVariableBinding;
25 | import org.eclipse.jdt.core.dom.Initializer;
26 | import org.eclipse.jdt.core.dom.Javadoc;
27 | import org.eclipse.jdt.core.dom.MethodDeclaration;
28 | import org.eclipse.jdt.core.dom.QualifiedName;
29 | import org.eclipse.jdt.core.dom.QualifiedType;
30 | import org.eclipse.jdt.core.dom.SimpleName;
31 | import org.eclipse.jdt.core.dom.SimpleType;
32 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
33 | import org.eclipse.jdt.core.dom.Statement;
34 | import org.eclipse.jdt.core.dom.TypeDeclaration;
35 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
36 |
37 | public class HeaderWriter extends TransformWriter {
38 | private final IPath root;
39 |
40 | private final Header header;
41 | private String access;
42 |
43 | public HeaderWriter(IPath root, Transformer ctx, UnitInfo unitInfo,
44 | TypeInfo typeInfo) {
45 | super(ctx, unitInfo, typeInfo);
46 | this.root = root;
47 |
48 | access = Header.initialAccess(type);
49 |
50 | header = new Header(ctx, type, deps);
51 | }
52 |
53 | public void write(AnnotationTypeDeclaration node) throws Exception {
54 | writeType(node.bodyDeclarations());
55 | }
56 |
57 | public void write(AnonymousClassDeclaration node) throws Exception {
58 | writeType(node.bodyDeclarations());
59 | }
60 |
61 | public void write(EnumDeclaration node) throws Exception {
62 | writeType(node.enumConstants(), node.bodyDeclarations());
63 | }
64 |
65 | public void write(TypeDeclaration node) throws Exception {
66 | writeType(node.bodyDeclarations());
67 | }
68 |
69 | private void writeType(List declarations) {
70 | writeType(new ArrayList(), declarations);
71 | }
72 |
73 | private void writeType(List enums,
74 | List declarations) {
75 | try {
76 | String body = getBody(enums, declarations);
77 |
78 | header.write(root, body, typeInfo.closures(), typeInfo.hasClinit(),
79 | typeInfo.hasInit(), unitInfo.types.keySet(), access);
80 | } catch (Exception e) {
81 | throw new Error(e);
82 | }
83 | }
84 |
85 | private String getBody(List enums,
86 | List declarations) {
87 | StringWriter sw = new StringWriter();
88 | out = new PrintWriter(sw);
89 |
90 | indent++;
91 |
92 | visitAll(enums);
93 |
94 | visitAll(declarations); // This will gather constructors
95 |
96 | indent--;
97 |
98 | out.close();
99 | out = null;
100 | return sw.toString();
101 | }
102 |
103 | @Override
104 | public boolean preVisit2(ASTNode node) {
105 | for (Snippet snippet : ctx.snippets) {
106 | if (!snippet.node(ctx, this, node)) {
107 | return false;
108 | }
109 | }
110 |
111 | return super.preVisit2(node);
112 | }
113 |
114 | private List> handledBlocks = new ArrayList>(
115 | Arrays.asList(TypeDeclaration.class));
116 |
117 | @Override
118 | public boolean visit(AnnotationTypeDeclaration node) {
119 | return false;
120 | }
121 |
122 | @Override
123 | public boolean visit(AnnotationTypeMemberDeclaration node) {
124 | printi();
125 | TransformUtil.printSignature(ctx, out, type, node.resolveBinding(),
126 | deps, false);
127 | // TODO defaults
128 | println(" = 0;");
129 | return false;
130 | }
131 |
132 | @Override
133 | public boolean visit(Block node) {
134 | if (!handledBlocks.contains(node.getParent().getClass())) {
135 | printlni("{");
136 |
137 | indent++;
138 |
139 | for (Object o : node.statements()) {
140 | Statement s = (Statement) o;
141 | s.accept(this);
142 | }
143 |
144 | indent--;
145 | printlni("}");
146 | println();
147 | }
148 |
149 | return false;
150 | }
151 |
152 | @Override
153 | public boolean visit(EnumDeclaration node) {
154 | return false;
155 | }
156 |
157 | @Override
158 | public boolean visit(EnumConstantDeclaration node) {
159 | access = Header.printAccess(out, node.getModifiers(), access);
160 | printi("static " + CName.of(type) + " *");
161 |
162 | node.getName().accept(this);
163 | println(";");
164 |
165 | return false;
166 | }
167 |
168 | @Override
169 | public boolean visit(FieldDeclaration node) {
170 | if (node.getJavadoc() != null) {
171 | node.getJavadoc().accept(this);
172 | }
173 |
174 | List fragments = node.fragments();
175 |
176 | int modifiers = node.getModifiers();
177 | if (TransformWriter.isAnySpecial(fragments)) {
178 | for (VariableDeclarationFragment f : fragments) {
179 | IVariableBinding vb = f.resolveBinding();
180 | boolean asMethod = TransformUtil.asMethod(vb);
181 | access = Header.printAccess(out, asMethod ? Modifier.PRIVATE
182 | : vb.getModifiers(), access);
183 |
184 | Object cv = TransformUtil.constexprValue(f);
185 | printi(TransformUtil.fieldModifiers(type, modifiers, true,
186 | cv != null));
187 |
188 | print(TransformUtil.varTypeCName(modifiers, vb.getType(), type,
189 | deps) + " ");
190 |
191 | f.accept(this);
192 |
193 | println(asMethod ? "_;" : ";");
194 | }
195 | } else {
196 | access = Header.printAccess(out, modifiers, access);
197 |
198 | printi(TransformUtil.fieldModifiers(type, modifiers, true, false));
199 |
200 | ITypeBinding tb = node.getType().resolveBinding();
201 | print(TransformUtil.varTypeCName(modifiers, tb, type, deps));
202 |
203 | print(" ");
204 |
205 | visitAllCSV(fragments, false);
206 |
207 | println(";");
208 | }
209 |
210 | return false;
211 | }
212 |
213 | @Override
214 | public boolean visit(Initializer node) {
215 | return false;
216 | }
217 |
218 | @Override
219 | public boolean visit(Javadoc node) {
220 | if (true)
221 | return false;
222 | printi("/** ");
223 | for (Iterator it = node.tags().iterator(); it.hasNext();) {
224 | ASTNode e = (ASTNode) it.next();
225 | e.accept(this);
226 | }
227 | println("\n */");
228 | return false;
229 | }
230 |
231 | @Override
232 | public boolean visit(MethodDeclaration node) {
233 | if (node.getJavadoc() != null) {
234 | node.getJavadoc().accept(this);
235 | }
236 |
237 | IMethodBinding mb = node.resolveBinding();
238 | if (TransformUtil.baseDeclared(ctx, type, mb)) {
239 | // Defining once more will lead to virtual inheritance issues
240 | printi("/*");
241 | TransformUtil.printSignature(ctx, out, type, mb, deps, false);
242 | println("; (already declared) */");
243 | return false;
244 | }
245 |
246 | header.method(mb);
247 |
248 | if (node.isConstructor()) {
249 | access = Header.printProtected(out, access);
250 |
251 | printi("void " + CName.CTOR + "(");
252 | String sep = TransformUtil.printEnumCtorParams(ctx, out, type, "",
253 | deps);
254 | if (!node.parameters().isEmpty()) {
255 | print(sep);
256 | }
257 | } else {
258 | access = Header.printAccess(out, mb, access);
259 |
260 | printi(TransformUtil.methodModifiers(mb));
261 | print(TransformUtil.typeParameters(node.typeParameters()));
262 |
263 | ITypeBinding rt = TransformUtil.returnType(type, node);
264 | softDep(rt);
265 | print(TransformUtil.relativeRef(rt, type, true) + " ");
266 |
267 | node.getName().accept(this);
268 | print("(");
269 |
270 | for (ITypeBinding rd : TransformUtil.returnDeps(type, mb,
271 | ctx.resolve(Object.class))) {
272 | hardDep(rd);
273 | }
274 | }
275 |
276 | visitAllCSV(node.parameters(), false);
277 |
278 | print(")");
279 |
280 | print(TransformUtil.throwsDecl(node.thrownExceptions()));
281 |
282 | print(TransformUtil.methodSpecifiers(mb));
283 |
284 | println(";");
285 |
286 | return false;
287 | }
288 |
289 | @Override
290 | public boolean visit(SimpleName node) {
291 | IBinding b = node.resolveBinding();
292 | if (b instanceof ITypeBinding) {
293 | softDep((ITypeBinding) b);
294 | print(CName.relative((ITypeBinding) b, type, false));
295 | return false;
296 | }
297 | return super.visit(node);
298 | }
299 |
300 | @Override
301 | public boolean visit(SimpleType node) {
302 | ITypeBinding b = node.resolveBinding();
303 | softDep(b);
304 | print(CName.relative(b, type, false));
305 | return false;
306 | }
307 |
308 | @Override
309 | public boolean visit(QualifiedName node) {
310 | IBinding b = node.resolveBinding();
311 | if (b instanceof ITypeBinding) {
312 | softDep((ITypeBinding) b);
313 | print(CName.relative((ITypeBinding) b, type, false));
314 | return false;
315 | }
316 | return super.visit(node);
317 | }
318 |
319 | @Override
320 | public boolean visit(QualifiedType node) {
321 | ITypeBinding b = node.resolveBinding();
322 | softDep(b);
323 | print(CName.relative(b, type, false));
324 | return false;
325 | }
326 |
327 | @Override
328 | public boolean visit(SingleVariableDeclaration node) {
329 | ITypeBinding tb = node.getType().resolveBinding();
330 |
331 | if (node.getExtraDimensions() > 0) {
332 | softDep(tb);
333 | tb = tb.createArrayType(node.getExtraDimensions());
334 | }
335 |
336 | if (node.isVarargs()) {
337 | tb = tb.createArrayType(1);
338 | print(TransformUtil.relativeRef(tb, type, true));
339 | print("/*...*/");
340 | } else {
341 | print(TransformUtil.varTypeCName(node.getModifiers(), tb, type,
342 | deps));
343 | }
344 |
345 | print(" ");
346 |
347 | node.getName().accept(this);
348 |
349 | return false;
350 | }
351 |
352 | @Override
353 | public boolean visit(TypeDeclaration node) {
354 | return false;
355 | }
356 |
357 | @Override
358 | public boolean visit(VariableDeclarationFragment node) {
359 | IVariableBinding vb = node.resolveBinding();
360 | ITypeBinding tb = vb.getType();
361 | header.field(vb);
362 | softDep(tb);
363 |
364 | node.getName().accept(this);
365 |
366 | String iv = TransformUtil.initialValue(vb);
367 | if (iv != null) {
368 | print(" { " + iv + " }");
369 | }
370 |
371 | return false;
372 | }
373 | }
374 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/InitInfo.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.eclipse.jdt.core.dom.ASTNode;
7 | import org.eclipse.jdt.core.dom.Initializer;
8 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
9 |
10 | /** init() or clinit() contents */
11 | public class InitInfo {
12 | /**
13 | * Strings constants that cannot be initialized directly in the header
14 | */
15 | public List strings = new ArrayList();
16 | public List nodes = new ArrayList();
17 |
18 | public InitInfo() {
19 | }
20 |
21 | public void add(Initializer initializer) {
22 | nodes.add(initializer);
23 | }
24 |
25 | public void add(VariableDeclarationFragment fragment) {
26 | assert (TransformUtil.initInInit(fragment));
27 | if (TransformUtil.constantValue(fragment) instanceof String) {
28 | strings.add(fragment);
29 | } else {
30 | nodes.add(fragment);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/MainWriter.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 |
6 | import org.eclipse.core.runtime.IPath;
7 | import org.eclipse.jdt.core.dom.ITypeBinding;
8 |
9 | public class MainWriter {
10 | private static final String MAIN_CPP_TMPL = "/se/arnetheduck/j2c/resources/Main.cpp.tmpl";
11 |
12 | public static String write(IPath root, ITypeBinding tb) throws IOException {
13 | String filename = TransformUtil.mainName(tb);
14 | String include = TransformUtil.include(tb);
15 | String qcname = CName.qualified(tb, true);
16 |
17 | File target = root.append("src").append(filename).toFile();
18 | FileUtil.writeTemplate(MAIN_CPP_TMPL, target, include, qcname);
19 | return filename;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/MakefileWriter.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.IOException;
4 | import java.util.Collection;
5 | import java.util.Set;
6 | import java.util.TreeSet;
7 |
8 | import org.eclipse.core.runtime.IPath;
9 |
10 | public class MakefileWriter {
11 | private static final String MAKEFILE_TMPL = "/se/arnetheduck/j2c/resources/Makefile.tmpl";
12 |
13 | public static class Info {
14 | public final Set impls = new TreeSet();
15 | public final Set stubs = new TreeSet();
16 | public final Set natives = new TreeSet();
17 | public final Set mains = new TreeSet();
18 | }
19 |
20 | private final IPath root;
21 |
22 | public MakefileWriter(IPath root) {
23 | this.root = root;
24 | }
25 |
26 | public void write(String name, Info sel, Info ext) throws IOException {
27 | FileUtil.writeTemplate(MAKEFILE_TMPL, root.append("Makefile").toFile(),
28 | name, list(sel.impls, ""), list(sel.stubs, ""),
29 | list(sel.natives, ""), list(ext.impls, "ext/"),
30 | list(ext.stubs, "ext/"), list(ext.natives, "ext/"),
31 | list(sel.mains, ""));
32 | }
33 |
34 | private static String list(Collection items, String prefix) {
35 | StringBuilder sb = new StringBuilder();
36 | for (String item : items) {
37 | sb.append("\t" + prefix + item + " \\\n");
38 | }
39 |
40 | return sb.toString();
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/Predicate.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | public interface Predicate {
4 | boolean apply(T t);
5 | }
6 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/Snippet.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import org.eclipse.jdt.core.dom.ASTNode;
4 | import org.eclipse.jdt.core.dom.IMethodBinding;
5 | import org.eclipse.jdt.core.dom.ITypeBinding;
6 | import org.eclipse.jdt.core.dom.IVariableBinding;
7 |
8 | public interface Snippet {
9 | boolean node(Transformer ctx, HeaderWriter w, ASTNode node);
10 |
11 | boolean node(Transformer ctx, ImplWriter w, ASTNode node);
12 |
13 | boolean type(Transformer ctx, TypeBindingHeaderWriter w, ITypeBinding tb);
14 |
15 | boolean field(Transformer ctx, TypeBindingHeaderWriter w,
16 | IVariableBinding vb);
17 |
18 | boolean method(Transformer ctx, TypeBindingHeaderWriter w, IMethodBinding mb);
19 |
20 | boolean prefix(Transformer ctx, StubWriter w, boolean natives);
21 |
22 | boolean suffix(Transformer ctx, StubWriter w, boolean natives);
23 |
24 | boolean field(Transformer ctx, StubWriter w, IVariableBinding vb);
25 |
26 | boolean method(Transformer ctx, StubWriter w, IMethodBinding mb);
27 |
28 | boolean body(Transformer ctx, StubWriter w, IMethodBinding mb);
29 | }
30 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/Stats.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import org.eclipse.jdt.core.dom.ITypeBinding;
4 |
5 | public class Stats {
6 | private enum Nesting {
7 | TOP_LEVEL, NESTED, LOCAL, ANONYMOUS
8 | }
9 |
10 | private enum Type {
11 | CLASS, INTERFACE, ENUM, ANNOTATION,
12 | }
13 |
14 | public int stats[][] = new int[Nesting.values().length][Type.values().length];
15 |
16 | public void add(ITypeBinding tb) {
17 | if (tb.isPrimitive() || tb.isArray()) {
18 | return;
19 | }
20 |
21 | Nesting nesting = Nesting.TOP_LEVEL;
22 | if (tb.isAnonymous()) {
23 | nesting = Nesting.ANONYMOUS;
24 | } else if (tb.isLocal()) {
25 | nesting = Nesting.LOCAL;
26 | } else if (tb.isNested()) {
27 | nesting = Nesting.NESTED;
28 | } else {
29 | if (!tb.isTopLevel()) {
30 | System.out.println(tb + " nesting?");
31 | }
32 | }
33 |
34 | Type type = Type.CLASS;
35 | if (tb.isAnnotation()) {
36 | type = Type.ANNOTATION;
37 | } else if (tb.isEnum()) {
38 | type = Type.ENUM;
39 | } else if (tb.isInterface()) {
40 | type = Type.INTERFACE;
41 | } else {
42 | if (!tb.isClass()) {
43 | System.out.println(tb + " type?");
44 | }
45 | }
46 |
47 | stats[nesting.ordinal()][type.ordinal()]++;
48 | }
49 |
50 | @Override
51 | public String toString() {
52 | StringBuilder sb = new StringBuilder();
53 | sb.append(String.format("%15s", ""));
54 | ;
55 | for (Nesting n : Nesting.values()) {
56 | sb.append(String.format("%15s", n));
57 | }
58 |
59 | sb.append('\n');
60 | for (Type t : Type.values()) {
61 | sb.append(String.format("%15s", t));
62 | for (Nesting n : Nesting.values()) {
63 | sb.append(String.format("%15s", stats[n.ordinal()][t.ordinal()]));
64 | }
65 |
66 | sb.append('\n');
67 | }
68 |
69 | return sb.toString();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/StubWriter.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.PrintWriter;
4 | import java.io.StringWriter;
5 | import java.lang.reflect.Modifier;
6 | import java.util.ArrayList;
7 | import java.util.Collection;
8 |
9 | import org.eclipse.core.runtime.IPath;
10 | import org.eclipse.jdt.core.dom.IMethodBinding;
11 | import org.eclipse.jdt.core.dom.ITypeBinding;
12 | import org.eclipse.jdt.core.dom.IVariableBinding;
13 |
14 | public class StubWriter {
15 | private static final String i1 = TransformUtil.indent(1);
16 |
17 | private final IPath root;
18 | private final Transformer ctx;
19 | private final ITypeBinding type;
20 |
21 | private final DepInfo deps;
22 |
23 | private Collection constructors = new ArrayList();
24 |
25 | private final Impl impl;
26 | private final String qcname;
27 | private final String name;
28 |
29 | private PrintWriter out;
30 |
31 | public StubWriter(IPath root, Transformer ctx, ITypeBinding type) {
32 | if (type.isInterface()) {
33 | throw new UnsupportedOperationException();
34 | }
35 |
36 | this.root = root;
37 | this.ctx = ctx;
38 | this.type = type;
39 |
40 | deps = new DepInfo(ctx);
41 | impl = new Impl(ctx, type, deps);
42 | qcname = CName.qualified(type, false);
43 | name = CName.of(type);
44 | }
45 |
46 | public void write(boolean natives, boolean privates) throws Exception {
47 | String body = getBody(natives, privates);
48 | String extras = getPrefix(natives);
49 | String suffix = getSuffix(natives);
50 |
51 | if (natives) {
52 | ctx.addNative(type);
53 | impl.write(root, extras + body + suffix, TransformUtil.NATIVE,
54 | null, null, natives);
55 | } else {
56 | ctx.addStub(type);
57 | impl.write(root, extras + body + suffix, TransformUtil.STUB, null,
58 | null, natives);
59 | }
60 | }
61 |
62 | private String getPrefix(boolean natives) {
63 | StringWriter sw = new StringWriter();
64 | out = new PrintWriter(sw);
65 |
66 | for (Snippet snippet : ctx.snippets) {
67 | if (!snippet.prefix(ctx, this, natives)) {
68 | return "";
69 | }
70 | }
71 |
72 | out.println("extern void unimplemented_(const char16_t* name);");
73 |
74 | if (!natives) {
75 | printDefaultInitCtor();
76 | printCtors();
77 | }
78 |
79 | out.close();
80 | out = null;
81 |
82 | return sw.toString();
83 | }
84 |
85 | private String getSuffix(boolean natives) {
86 | StringWriter sw = new StringWriter();
87 | out = new PrintWriter(sw);
88 |
89 | for (Snippet snippet : ctx.snippets) {
90 | if (!snippet.suffix(ctx, this, natives)) {
91 | return "";
92 | }
93 | }
94 |
95 | out.close();
96 | out = null;
97 |
98 | return sw.toString();
99 | }
100 |
101 | private String getBody(boolean natives, boolean privates) throws Exception {
102 | StringWriter ret = new StringWriter();
103 | out = new PrintWriter(ret);
104 |
105 | if (!natives) {
106 | for (IVariableBinding vb : type.getDeclaredFields()) {
107 | printField(vb);
108 | }
109 | }
110 |
111 | println();
112 |
113 | for (IMethodBinding mb : type.getDeclaredMethods()) {
114 | if (Modifier.isNative(mb.getModifiers()) == natives) {
115 | printMethod(mb, privates);
116 | }
117 | }
118 |
119 | out.close();
120 |
121 | out = null;
122 |
123 | return ret.toString();
124 | }
125 |
126 | private void printCtors() {
127 | if (!TypeUtil.isClassLike(type)) {
128 | return;
129 | }
130 |
131 | if (type.isAnonymous()) {
132 | Header.getAnonCtors(type, constructors);
133 | }
134 |
135 | boolean hasEmpty = false;
136 | for (IMethodBinding mb : constructors) {
137 | print(qcname + "::" + name + "(");
138 |
139 | String sep = TransformUtil.printExtraCtorParams(ctx, out, type,
140 | null, deps, false, mb);
141 |
142 | if (mb.getParameterTypes().length > 0) {
143 | print(sep);
144 | TransformUtil.printParams(out, type, mb, false, deps);
145 | } else {
146 | hasEmpty = true;
147 | }
148 |
149 | println(")");
150 |
151 | print(i1 + ": " + name + "(");
152 | sep = "";
153 | if (TransformUtil.hasOuterThis(type)) {
154 | print(TransformUtil.outerThisName(type));
155 | sep = ", ";
156 | }
157 |
158 | println(sep + TransformUtil.makeDefaultInitTag() + ")");
159 |
160 | println("{");
161 | print(i1 + CName.CTOR + "(");
162 |
163 | sep = TransformUtil.printEnumCtorCallParams(out, type, "");
164 | for (int i = 0; i < mb.getParameterTypes().length; ++i) {
165 | print(sep + TransformUtil.paramName(mb, i));
166 | sep = ", ";
167 | }
168 |
169 | println(");");
170 |
171 | println("}");
172 | println();
173 | }
174 |
175 | if (TransformUtil.needsEmptyCtor(hasEmpty, false, type)) {
176 | printEmptyCtor();
177 | }
178 | }
179 |
180 | private void printDefaultInitCtor() {
181 | if (!TypeUtil.isClassLike(type) || type.isAnonymous()) {
182 | return;
183 | }
184 |
185 | print(qcname + "::" + name + "(");
186 | TransformUtil.printExtraCtorParams(ctx, out, type, null, deps, true,
187 | null);
188 | println(")");
189 |
190 | printFieldInit(": ");
191 |
192 | println("{");
193 | printClInitCall();
194 | println("}");
195 | println();
196 |
197 | }
198 |
199 | private void printClInitCall() {
200 | println(i1 + CName.STATIC_INIT + "();");
201 | }
202 |
203 | private void printEmptyCtor() {
204 | print("void " + qcname + "::" + CName.CTOR + "(");
205 | TransformUtil.printEnumCtorParams(ctx, out, type, "", deps);
206 | println(")");
207 | println("{");
208 | if (type.getSuperclass() != null) {
209 | print(i1 + "super::");
210 | TransformUtil.printEmptyCtorCall(out, type);
211 | println(";");
212 | }
213 |
214 | println("}");
215 | println();
216 | }
217 |
218 | private void printFieldInit(String sep) {
219 | ITypeBinding sb = type.getSuperclass();
220 | if (sb != null) {
221 | print(i1 + sep);
222 | print("super(");
223 | if (TransformUtil.hasOuterThis(sb)) {
224 | String sepx = "";
225 | for (ITypeBinding tb = type; tb.getDeclaringClass() != null; tb = tb
226 | .getDeclaringClass().getErasure()) {
227 | print(sepx);
228 | sepx = "->";
229 | hardDep(tb.getDeclaringClass());
230 | print(TransformUtil.outerThisName(tb));
231 | if (tb.getDeclaringClass()
232 | .getErasure()
233 | .isSubTypeCompatible(
234 | sb.getDeclaringClass().getErasure())) {
235 | break;
236 | }
237 |
238 | }
239 |
240 | print(", ");
241 | }
242 |
243 | println(TransformUtil.makeDefaultInitTag() + ")");
244 | sep = ", ";
245 | }
246 |
247 | if (TransformUtil.hasOuterThis(type)
248 | && (sb == null || sb.getDeclaringClass() == null || !type
249 | .getDeclaringClass().getErasure()
250 | .isEqualTo(sb.getDeclaringClass().getErasure()))) {
251 | print(i1 + sep);
252 | hardDep(type.getDeclaringClass());
253 | printInit(TransformUtil.outerThisName(type));
254 | sep = ", ";
255 | }
256 |
257 | for (IVariableBinding vb : type.getDeclaredFields()) {
258 | if (TransformUtil.isStatic(vb)) {
259 | continue;
260 | }
261 |
262 | if (TransformUtil.initialValue(vb) != null) {
263 | continue;
264 | }
265 |
266 | // TODO Init string literals
267 | print(i1 + sep + CName.of(vb));
268 |
269 | println("()");
270 | sep = ", ";
271 |
272 | }
273 | }
274 |
275 | private void printInit(String n) {
276 | println(n + "(" + n + ")");
277 | }
278 |
279 | private void printField(IVariableBinding vb) {
280 | for (Snippet snippet : ctx.snippets) {
281 | if (!snippet.field(ctx, this, vb)) {
282 | return;
283 | }
284 | }
285 |
286 | if (!TransformUtil.isStatic(vb)) {
287 | return;
288 | }
289 |
290 | Object cv = TransformUtil.constexprValue(vb);
291 | boolean asMethod = TransformUtil.asMethod(vb);
292 |
293 | ITypeBinding vt = vb.getType();
294 | String vname = CName.of(vb);
295 | String qvtname = TransformUtil
296 | .varTypeCName(vb.getModifiers(), vt, deps);
297 | if (asMethod) {
298 | print(qvtname);
299 | println("& " + qcname + "::" + vname + "()");
300 | println("{");
301 | printClInitCall();
302 | println(i1 + "return " + vname + "_;");
303 | println("}");
304 | }
305 |
306 | print(TransformUtil.fieldModifiers(type, vb.getModifiers(), false,
307 | cv != null && !(cv instanceof String)));
308 |
309 | print(qvtname + " " + qcname + "::" + vname);
310 | println(asMethod ? "_;" : ";");
311 | }
312 |
313 | private void printMethod(IMethodBinding mb, boolean privates)
314 | throws Exception {
315 | for (Snippet snippet : ctx.snippets) {
316 | if (!snippet.method(ctx, this, mb)) {
317 | return;
318 | }
319 | }
320 |
321 | if (Modifier.isPrivate(mb.getModifiers()) && !privates) {
322 | if (Modifier.isAbstract(mb.getModifiers())) {
323 | return;
324 | }
325 |
326 | print("/* private: ");
327 | TransformUtil.printSignature(ctx, out, type, mb, deps, true);
328 | println(" */");
329 | return;
330 | }
331 |
332 | impl.method(mb);
333 |
334 | if (Modifier.isAbstract(mb.getModifiers())) {
335 | return;
336 | }
337 |
338 | if (mb.isConstructor()) {
339 | constructors.add(mb);
340 | }
341 |
342 | TransformUtil.printSignature(ctx, out, type, mb, deps, true);
343 |
344 | println();
345 | print("{");
346 | if (Modifier.isNative(mb.getModifiers())) {
347 | println(" /* native */");
348 | } else {
349 | println(" /* stub */");
350 | }
351 |
352 | if (TransformUtil.isStatic(mb)) {
353 | printClInitCall();
354 | }
355 |
356 | if (mb.isConstructor() && type.getSuperclass() != null) {
357 | // Remind the user that this has to be done one way or another
358 | // TODO Maybe try to find a suitable candidate to pass as many
359 | // parameters as possible
360 | println(i1 + "/* super::" + CName.CTOR + "(); */");
361 | }
362 |
363 | boolean hasBody = false;
364 | for (Snippet snippet : ctx.snippets) {
365 | if (!snippet.body(ctx, this, mb)) {
366 | hasBody = true;
367 | break;
368 | }
369 | }
370 |
371 | if (!hasBody) {
372 | print(i1 + "unimplemented_(u\"");
373 | TransformUtil.printSignature(ctx, out, type, mb, deps, true);
374 | println("\");");
375 | if (!TransformUtil.isVoid(mb.getReturnType())) {
376 | println(i1 + "return 0;");
377 | }
378 | }
379 |
380 | println("}");
381 | println();
382 |
383 | TransformUtil.defineBridge(ctx, out, type, mb, deps);
384 | }
385 |
386 | public void hardDep(ITypeBinding dep) {
387 | deps.hard(dep);
388 | }
389 |
390 | public void print(String string) {
391 | out.print(string);
392 | }
393 |
394 | public void println(String string) {
395 | out.println(string);
396 | }
397 |
398 | public void println() {
399 | out.println();
400 | }
401 |
402 | public ITypeBinding type() {
403 | return type;
404 | }
405 | }
406 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/TypeBindingHeaderWriter.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.io.PrintWriter;
4 | import java.io.StringWriter;
5 | import java.lang.reflect.Modifier;
6 | import java.util.ArrayList;
7 |
8 | import org.eclipse.core.runtime.IPath;
9 | import org.eclipse.jdt.core.dom.IMethodBinding;
10 | import org.eclipse.jdt.core.dom.ITypeBinding;
11 | import org.eclipse.jdt.core.dom.IVariableBinding;
12 |
13 | public class TypeBindingHeaderWriter {
14 | private final IPath root;
15 | private final ITypeBinding type;
16 | private final Transformer ctx;
17 |
18 | private final DepInfo deps;
19 |
20 | private String access;
21 | private final Header header;
22 | private static final String i1 = TransformUtil.indent(1);
23 |
24 | public TypeBindingHeaderWriter(IPath root, Transformer ctx,
25 | ITypeBinding type) {
26 | this.root = root;
27 | this.ctx = ctx;
28 | this.type = type;
29 |
30 | deps = new DepInfo(ctx);
31 | access = Header.initialAccess(type);
32 | softDep(type);
33 | header = new Header(ctx, type, deps);
34 | }
35 |
36 | public void write() throws Exception {
37 | writeType();
38 |
39 | if (!type.isInterface()) {
40 | StubWriter sw = new StubWriter(root, ctx, type);
41 | sw.write(false, false);
42 | if (hasNatives()) {
43 | sw = new StubWriter(root, ctx, type);
44 | sw.write(true, false);
45 | }
46 | }
47 | }
48 |
49 | private boolean hasNatives() {
50 | for (IMethodBinding mb : type.getDeclaredMethods()) {
51 | if (Modifier.isNative(mb.getModifiers())) {
52 | return true;
53 | }
54 | }
55 |
56 | return false;
57 | }
58 |
59 | private void writeType() throws Exception {
60 | for (ITypeBinding nb : type.getDeclaredTypes()) {
61 | TypeBindingHeaderWriter hw = new TypeBindingHeaderWriter(root, ctx,
62 | nb);
63 | hw.write();
64 | }
65 |
66 | try {
67 | String body = getBody();
68 |
69 | header.write(root, body, new ArrayList(), false,
70 | false, new ArrayList(), access);
71 | } catch (Exception e) {
72 | throw new Error(e);
73 | }
74 | }
75 |
76 | private String getBody() {
77 | StringWriter sw = new StringWriter();
78 | PrintWriter out = new PrintWriter(sw);
79 |
80 | for (IVariableBinding vb : type.getDeclaredFields()) {
81 | header.field(vb);
82 | printField(out, vb);
83 | }
84 |
85 | out.println();
86 |
87 | for (IMethodBinding mb : type.getDeclaredMethods()) {
88 | printMethod(out, mb);
89 | }
90 |
91 | return sw.toString();
92 | }
93 |
94 | private void printField(PrintWriter pw, IVariableBinding vb) {
95 | ITypeBinding tb = vb.getType();
96 | softDep(tb);
97 |
98 | boolean asMethod = TransformUtil.asMethod(vb);
99 | int modifiers = vb.getModifiers();
100 | access = Header.printAccess(pw,
101 | asMethod ? Modifier.PRIVATE : modifiers, access);
102 | pw.print(TransformUtil.indent(1));
103 |
104 | Object cv = TransformUtil.constexprValue(vb);
105 | pw.print(TransformUtil
106 | .fieldModifiers(type, modifiers, true, cv != null));
107 |
108 | pw.print(TransformUtil.varTypeCName(modifiers, tb,
109 | vb.getDeclaringClass(), deps));
110 | pw.print(" ");
111 |
112 | pw.print(CName.of(vb));
113 | pw.print(asMethod ? "_" : "");
114 |
115 | String iv = TransformUtil.initialValue(vb);
116 | if (iv != null) {
117 | pw.print(" { " + iv + " }");
118 | }
119 |
120 | pw.println(";");
121 | }
122 |
123 | private void printMethod(PrintWriter pw, IMethodBinding mb) {
124 | if (TransformUtil.baseDeclared(ctx, type, mb)) {
125 | // Defining once more will lead to virtual inheritance issues
126 | pw.print(i1 + "/*");
127 | TransformUtil.printSignature(ctx, pw, type, mb, deps, false);
128 | pw.println("; (already declared) */");
129 | return;
130 | }
131 |
132 | if (Modifier.isPrivate(mb.getModifiers())) {
133 | // Skip implementation details
134 | pw.print(i1 + "/*");
135 | TransformUtil.printSignature(ctx, pw, type, mb, deps, false);
136 | pw.println("; (private) */");
137 | return;
138 | }
139 |
140 | if (mb.isConstructor()) {
141 | // The fake ctor should always be protected
142 | access = Header.printProtected(pw, access);
143 | } else {
144 | access = Header.printAccess(pw, mb.getModifiers(), access);
145 | }
146 |
147 | header.method(mb);
148 |
149 | pw.print(i1);
150 | TransformUtil.printSignature(ctx, pw, type, mb, deps, false);
151 |
152 | pw.print(TransformUtil.methodSpecifiers(mb));
153 |
154 | pw.println(";");
155 |
156 | for (ITypeBinding rd : TransformUtil.returnDeps(type, mb,
157 | ctx.resolve(Object.class))) {
158 | hardDep(rd);
159 | }
160 | }
161 |
162 | public void hardDep(ITypeBinding dep) {
163 | deps.hard(dep);
164 | }
165 |
166 | public void softDep(ITypeBinding dep) {
167 | deps.soft(dep);
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/TypeInfo.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.util.LinkedHashSet;
4 | import java.util.Set;
5 |
6 | import org.eclipse.jdt.core.dom.ITypeBinding;
7 | import org.eclipse.jdt.core.dom.IVariableBinding;
8 | import org.eclipse.jdt.core.dom.Initializer;
9 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
10 |
11 | /** Contextual info about a type */
12 | public class TypeInfo {
13 | private final TypeInfo parent;
14 | private final ITypeBinding type;
15 |
16 | private InitInfo init = new InitInfo();
17 | private InitInfo clinit = new InitInfo();
18 |
19 | private final Set closures;
20 | private boolean natives;
21 | private boolean main;
22 |
23 | public TypeInfo(TypeInfo parent, ITypeBinding type) {
24 | this.parent = parent;
25 | this.type = type;
26 |
27 | closures = type.isLocal() ? new LinkedHashSet()
28 | : null;
29 | }
30 |
31 | public TypeInfo parent() {
32 | return parent;
33 | }
34 |
35 | public ITypeBinding type() {
36 | return type;
37 | }
38 |
39 | public boolean hasNatives() {
40 | return natives;
41 | }
42 |
43 | public void setHasNatives() {
44 | natives = true;
45 | }
46 |
47 | public boolean hasMain() {
48 | return main;
49 | }
50 |
51 | public void setHasMain() {
52 | main = true;
53 | }
54 |
55 | public void addInit(VariableDeclarationFragment fragment) {
56 | getInit(TransformUtil.isStatic(fragment)).add(fragment);
57 | }
58 |
59 | public void addInit(Initializer initializer) {
60 | getInit(TransformUtil.isStatic(initializer)).add(initializer);
61 | }
62 |
63 | public InitInfo getInit(boolean static_) {
64 | return static_ ? clinit : init;
65 | }
66 |
67 | public boolean hasInit() {
68 | // strings are not part of init()
69 | return !init.nodes.isEmpty();
70 | }
71 |
72 | public boolean hasClinit() {
73 | return !clinit.nodes.isEmpty() || !clinit.strings.isEmpty();
74 | }
75 |
76 | public void addClosure(IVariableBinding closure) {
77 | closures.add(closure);
78 | }
79 |
80 | public Set closures() {
81 | return closures;
82 | }
83 |
84 | public boolean isClosure(IVariableBinding vb) {
85 | return closures != null && closures.contains(vb);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/TypeInfoVisitor.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import org.eclipse.jdt.core.IJavaElement;
4 | import org.eclipse.jdt.core.IType;
5 | import org.eclipse.jdt.core.dom.ASTNode;
6 | import org.eclipse.jdt.core.dom.ASTVisitor;
7 | import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
8 | import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
9 | import org.eclipse.jdt.core.dom.EnumDeclaration;
10 | import org.eclipse.jdt.core.dom.IBinding;
11 | import org.eclipse.jdt.core.dom.IMethodBinding;
12 | import org.eclipse.jdt.core.dom.ITypeBinding;
13 | import org.eclipse.jdt.core.dom.IVariableBinding;
14 | import org.eclipse.jdt.core.dom.Initializer;
15 | import org.eclipse.jdt.core.dom.MethodDeclaration;
16 | import org.eclipse.jdt.core.dom.Modifier;
17 | import org.eclipse.jdt.core.dom.SimpleName;
18 | import org.eclipse.jdt.core.dom.TypeDeclaration;
19 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
20 |
21 | public class TypeInfoVisitor extends ASTVisitor {
22 | private UnitInfo unitInfo;
23 | private TypeInfo typeInfo;
24 |
25 | public TypeInfoVisitor(UnitInfo unitInfo) {
26 | this.unitInfo = unitInfo;
27 | }
28 |
29 | @Override
30 | public boolean visit(AnnotationTypeDeclaration node) {
31 | typeInfo = new TypeInfo(typeInfo, node.resolveBinding());
32 | unitInfo.types.put(typeInfo.type(), typeInfo);
33 | return true;
34 | }
35 |
36 | @Override
37 | public void endVisit(AnnotationTypeDeclaration node) {
38 | typeInfo = typeInfo.parent();
39 | }
40 |
41 | @Override
42 | public boolean visit(AnonymousClassDeclaration node) {
43 | typeInfo = new TypeInfo(typeInfo, node.resolveBinding());
44 | unitInfo.types.put(typeInfo.type(), typeInfo);
45 | return true;
46 | }
47 |
48 | @Override
49 | public void endVisit(AnonymousClassDeclaration node) {
50 | TypeInfo anonType = typeInfo;
51 | typeInfo = typeInfo.parent();
52 |
53 | if (typeInfo.closures() != null && anonType.closures() != null) {
54 | for (IVariableBinding vb : anonType.closures()) {
55 | if (!vb.getDeclaringMethod().getDeclaringClass()
56 | .isEqualTo(typeInfo.type())) {
57 | typeInfo.addClosure(vb);
58 | }
59 | }
60 | }
61 | }
62 |
63 | @Override
64 | public boolean visit(EnumDeclaration node) {
65 | typeInfo = new TypeInfo(typeInfo, node.resolveBinding());
66 | unitInfo.types.put(typeInfo.type(), typeInfo);
67 | return true;
68 | }
69 |
70 | @Override
71 | public void endVisit(EnumDeclaration node) {
72 | typeInfo = typeInfo.parent();
73 | }
74 |
75 | @Override
76 | public boolean visit(MethodDeclaration node) {
77 | if (Modifier.isNative(node.getModifiers())) {
78 | typeInfo.setHasNatives();
79 | }
80 |
81 | if (TransformUtil.isMain(node.resolveBinding())) {
82 | typeInfo.setHasMain();
83 | }
84 |
85 | return true;
86 | }
87 |
88 | @Override
89 | public boolean visit(TypeDeclaration node) {
90 | typeInfo = new TypeInfo(typeInfo, node.resolveBinding());
91 | unitInfo.types.put(typeInfo.type(), typeInfo);
92 | return true;
93 | }
94 |
95 | @Override
96 | public void endVisit(TypeDeclaration node) {
97 | typeInfo = typeInfo.parent();
98 | }
99 |
100 |
101 | @Override
102 | public boolean visit(Initializer node) {
103 | typeInfo.addInit(node);
104 | return super.visit(node);
105 | }
106 |
107 | @Override
108 | public boolean visit(SimpleName node) {
109 | IBinding b = node.resolveBinding();
110 | if (b instanceof IVariableBinding) {
111 | IVariableBinding vb = (IVariableBinding) b;
112 |
113 | if (isClosure(node, vb)) {
114 | typeInfo.addClosure(vb);
115 | }
116 | }
117 |
118 | return super.visit(node);
119 | }
120 |
121 | @Override
122 | public boolean visit(VariableDeclarationFragment node) {
123 | if (TransformUtil.initInInit(node)) {
124 | typeInfo.addInit(node);
125 | }
126 |
127 | return super.visit(node);
128 | }
129 |
130 | private boolean isClosure(SimpleName node, IVariableBinding vb) {
131 | if (vb.isField()) {
132 | return false;
133 | }
134 |
135 | if (vb.getDeclaringMethod() == null) {
136 | IJavaElement je = vb.getJavaElement().getAncestor(
137 | IJavaElement.INITIALIZER);
138 |
139 | // Could be a variable in an initializer block
140 | if (je == null
141 | || (((IType) je.getAncestor(IJavaElement.TYPE))
142 | .getFullyQualifiedName().equals(((IType) type()
143 | .getJavaElement()).getFullyQualifiedName()))) {
144 | return false;
145 | }
146 | }
147 |
148 | if (!Modifier.isFinal(vb.getModifiers())) {
149 | return false;
150 | }
151 | VariableDeclarationFragment vdf = initializer(node);
152 | if (vdf == null && vb.getDeclaringMethod() != null) {
153 | IMethodBinding pmb = parentMethod(node);
154 | if (pmb.isEqualTo(vb.getDeclaringMethod())) {
155 | // Final local variable
156 | return false;
157 | }
158 | }
159 | return true;
160 | }
161 |
162 | private static IMethodBinding parentMethod(ASTNode node) {
163 | for (ASTNode n = node; n != null; n = n.getParent()) {
164 | if (n instanceof MethodDeclaration) {
165 | return ((MethodDeclaration) n).resolveBinding();
166 | }
167 | }
168 |
169 | return null;
170 | }
171 |
172 | private VariableDeclarationFragment initializer(ASTNode node) {
173 | for (ASTNode n = node; n != null; n = n.getParent()) {
174 | if (n.getParent() instanceof VariableDeclarationFragment) {
175 | VariableDeclarationFragment vdf = (VariableDeclarationFragment) n
176 | .getParent();
177 | if (type().isEqualTo(vdf.resolveBinding().getDeclaringClass())
178 | && vdf.getInitializer() == n) {
179 | return vdf;
180 | }
181 | }
182 | }
183 |
184 | return null;
185 | }
186 |
187 | private ITypeBinding type() {
188 | return typeInfo.type();
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/plugin/src/se/arnetheduck/j2c/transform/TypeUtil.java:
--------------------------------------------------------------------------------
1 | package se.arnetheduck.j2c.transform;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.List;
6 |
7 | import org.eclipse.jdt.core.dom.IMethodBinding;
8 | import org.eclipse.jdt.core.dom.ITypeBinding;
9 | import org.eclipse.jdt.core.dom.IVariableBinding;
10 |
11 | /** Utilities for traversing the type hierarchy */
12 | public class TypeUtil {
13 | public static Predicate