SkillAgentSearch skills...

JavaPy

Program Java with Python indentation!

Install / Use

/learn @raptor494/JavaPy
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

JavaPy

Description

This is a Java preprocessor, written in Python, which allows you to write Java using Python indentation and without semicolons. I wrote it in my spare time, so there may be lots of bugs. I tried to support every syntactical element in the Java language that I could, including new constructs from Java 12 and 13 (switch expressions and the yield statement).

Usage

Call the program with python javapy.py <filename> and it will output a file called the same thing except with a .java extension. The program tries to format the file to be human-readable but may not be quite right in places. Use your own formatter as necessary. The parser does not check for semantically invalid syntax, such as duplicate variable names, duplicate methods, improper package names, illegal modifiers, etc.

Differences from Normal Java

Code Blocks

Blocks are usually not allowed anymore. Instead of blocks, use a Python Suite, which is a colon followed by a series of elements all indented the same amount.

Examples:

Normal Java:

public class Example {
    public static final int x, y;
} 

JavaPy:

public class Example:
    public static final int x, y

_______________________________________________________________________

Normal Java:

public int foo(int x) {
    if(x < 10) {
        return 2*x - 1;
    } else {
        return x % 3 * x - 6;
    }
}

JavaPy:

public int foo(int x):
    if x < 10:
        return 2*x - 1
    else:
        return x % 3 * x - 6

Statements containing other statements

If a statement would normally require a parenthesised condition after its keyword, the parenthesis are now optional.

Examples:

Normal Java:

if(condition) {
    doSomething();
} else if(anotherCondition) {
    doSomethingElse();
} else {
    doSomething2();
}

JavaPy:

if condition:
    doSomething()
else if anotherCondition:
    doSomethingElse()
else:
    doSomething2()

_______________________________________________________________________

Normal Java:

synchronized(this) {
    doSomethingWithThis();
}

JavaPy:

synchronized: // If you leave the lock expression out, it defaults to 'this'.
    doSomethingWithThis()

_______________________________________________________________________

Normal Java:

try(Scanner keys = new Scanner(System.in)) {
    System.out.print("Enter a number: ");
    int x = Integer.parseInt(keys.nextLine());
    System.out.println("Your number was: " + x);
} catch(NumberFormatException e) {
    e.printStackTrace();
} finally {
    System.out.println("Goodbye");
}

JavaPy:

try var keys = new Scanner(System.in):
    System.out.print("Enter a number: ")
    int x = Integer.parseInt(keys.nextLine())
    System.out.println("Your number was: " + x)
catch NumberFormatException e:
    e.printStackTrace()
finally:
    System.out.println("Goodbye")

Import Declarations

The one statement I have brought over from python is the from ... import ... statement. Syntax: from <package-or-type-name> import [static] <qualified-name-or-wildcard> {, <qualified-name-or-wildcard>}

Examples:

Normal Java:

import java.util.List;
import java.util.ArrayList;
import java.util.Map;

JavaPy:

from java.util import List, ArrayList, Map

_______________________________________________________________________

Normal Java:

import static com.test.Example.foo;
import static com.test.Example.bar;
import static com.test.Example.kaz;

JavaPy:

from com.test.Example import static  foo, bar, kaz
<!-- No matter what I try, I cannot get all three keywords to be highlighted (from, import, static). Even though JavaScript has all three keywords, and the highlighting works as I want it to in the VS Code preview, GitHub for whatever reason only highlights 'import'. So, I'll just stick with Java for now. -->

_______________________________________________________________________

Normal Java:

import java.util.*;
import java.util.function.*;

JavaPy:

from java.util import *, function.*

Additionally, a single normal import statement can have multiple comma-separated imports in it.

Example:

import java.util.List, java.util.ArrayList

Optional parenthesis

Sometimes, you may want to put certain things on multiple lines. You could end a line with a backslash (\) to join it with the following line, like in Python, or you could wrap it in parenthesis.

Examples:

Normal Java:

for(int x = aVeryLongExpression(), 
        y = anotherVeryLongExpression(), 
        z = yetAnotherVeryLongExpression();
    x + y < z; 
    x++, y--, z--) {
    System.out.println(x+y+z);
}

JavaPy:

for (int x = aVeryLongExpression(),
         y = anotherVeryLongExpression(), 
         z = yetAnotherVeryLongExpression()); \
        x + y < z; \
        x++, y++, z++:
    System.out.println(x+y+z)

_______________________________________________________________________

Normal Java:

public abstract class Example extends Superclass implements Interface1,     
    Interface2, 
    Interface3,
    Interface4 {
    ...
}

JavaPy:

public abstract class Example extends Superclass implements (Interface1,
    Interface2,
    Interface3,
    Interface4):
    ;

_______________________________________________________________________

Normal Java:

module com.test {
    exports com.test.types;
    requires com.example.services;
    provides com.example.services.ExampleService with com.test.services.MyService,
        com.test.services.TheirService;
}

JavaPy:

module com.test:
    exports com.test.types
    requires com.example.services
    provides com.example.services.ExampleService with (com.test.services.MyService,
        com.test.services.TheirService)

_______________________________________________________________________

Normal Java:

HashMap<String, 
    HashMap<Integer, 
        List<Pair<String, ?>>>> map = new HashMap<>();

JavaPy:

HashMap<(String,
    HashMap<Integer,
        List<Pair<String, ?>>>)> map = new HashMap<>()

_______________________________________________________________________

Normal Java:

try(var resource1 = getResource1();
    var resource2 = getResource2()) {
    doStuffWithResources();
} catch(NoSuchElementException 
        | NullPointerException 
        | ClassNotFoundException 
        | IllegalArgumentException e) {
    e.printStackTrace();
} catch(IOException
        | IllegalStateException e) {
    e.printStackTrace();
}

JavaPy:

try (var resource1 = getResource1();
     var resource2 = getResource2()):
    doStuffWithResources()
catch (NoSuchElementException 
        | NullPointerException 
        | ClassNotFoundException 
        | IllegalArgumentException) e:
    e.printStackTrace()
catch (IOException
        | IllegalStateException e):
    e.printStackTrace()

_______________________________________________________________________

Normal Java:

switch(day) {
    case MONDAY,
        TUESDAY,
        WEDNESDAY -> {
            if(day == Day.MONDAY) {
                message = "It's a monday";
            } else {
                message = "meh";
            }
        }
    case THURSDAY, FRIDAY -> {
        message = "Almost";
    }
    default -> throw new WeekendException();
}

JavaPy:

switch day:
    case (MONDAY,
          TUESDAY,
          WEDNESDAY) ->
        if day == Day.MONDAY:
            message = "It's a monday"
        else:
            message = "meh"
    case THURSDAY, FRIDAY -> message = "Almost"
    default -> throw new WeekendException()

_______________________________________________________________________

Normal Java:

import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;

JavaPy:

from java.util import (
    List,
    Set,
    Map,
    ArrayList,
    HashSet,
    HashMap
)

Unnecessary Commas

In Java, you can add a comma at the end of a list initializer:

int[] ints = {1,2,3,4,5,};

Python has that, plus allows you to do it in function arguments. Thus, JavaPy allows you to do it in function arguments, too.

foo(1,2,3,4,5,)

Places where blocks ARE needed

In some places, I just couldn't do the Suite syntax for a code block, like in lambda expressions or anonymous classes. So, for those, you'll just need to wrap the block in braces (Note that the block still needs to be indented).

Examples:

Normal Java:

new Object() {
    public void foo() {
        System.out.println("Foo");
    }
}

JavaPy:

new Object() {
    public void foo():
        System.out.println("Foo")
}

_______________________________________________________________________

Normal Java:

(String str, int x) -> {
    if(str == null) {
        System.out.println("Str is null");
    } else {
        assert Integer.parseInt(str) == x;
    }
}

JavaPy:

(String str, int x) -> {
    if str == null:
        System.out.println("Str is null")
    else:
        assert Integer.parseInt(str) == x
}

Additions

String Literals

A happy consequence of using a modified version of the standard Python tokenize module is that most* of Python's string literals are supported.

r"This is a raw string, useful for writing regexes or Windows file locations:"
    r"C:\Users\user\Documents\GitHub\JavaPy\README.md"

R"This is also a raw string. VS Code highlighters generally highlight the lower-case"

R"'r' string literal as a regex, but leave this one alone."

""" This is a multi-line string.
    It can span several lines with ease.
    Unlike Java 14's text blocks, the first line can appear right after the opening quotes. 
    I may or may not change this in the future wh
View on GitHub
GitHub Stars59
CategoryDevelopment
Updated4y ago
Forks3

Languages

Python

Security Score

80/100

Audited on Dec 31, 2021

No findings