java:S1120 Incorrect indentation policy

Please provide

  • Operating system:
    • Ubuntu 22.04.3 LTS
    • Kernel: Linux 6.5.0-14-generic
  • SonarLint plugin version: v4.2.2
  • Programming language you’re coding in: Java
  • Is connected mode used: No
    • Connected to SonarCloud or SonarQube (and which version): -
  • VSCode version: 1.85.2
    And a thorough description of the problem / question:

When using an Enum class with an abstract method, this rule informs a wrong multiple of the current indentation used.

Example enum that breaks the rule:

public enum Operations {
	ADD {
		@Override
		public double operate(double a, double b) {
			return a + b;
		}
	},
	SUB {
		@Override
		public double operate(double a, double b) {
			return a - b;
		}
	},
	MULT {
		@Override
		public double operate(double a, double b) {
			return a * b;
		}
	},
	DIV {
		@Override
		public double operate(double a, double b) {
			return a / b;
		}
	};
	public abstract double operate(double a, double b);
}

In this example class, using a tab size 4, the rule will incorrectly state for the overriden methods inside the enum constants:

For the methods: Make this line start after 5 spaces instead of 8 in order to indent the code consistently. (Indentation leve is at 4.)

For the return statements: Make this line start after 9 spaces instead of 12 in order to indent the code consistently. (Indentation leve is at 4.)

Picture from the IDE:

If this is a duplicate, sorry. I tried searching for it but didn’t find anything.

Hello @marinello and welcome to the Sonar Community.

It seems that your code block is not using indentation level 4. Here is how the correctly indented file should be:

public enum Operations {
    ADD {
        @Override
        public double operate(double a, double b) {
            return a + b;
        }
    },
    SUB {
        @Override
        public double operate(double a, double b) {
            return a - b;
        }
    },
    MULT {
        @Override
        public double operate(double a, double b) {
            return a * b;
        }
    },
    DIV {
        @Override
        public double operate(double a, double b) {
            return a / b;
        }
    };
	public abstract double operate(double a, double b);
}

I hope this helps you.

Cheers,
Angelo

Thanks for the reply @ angelo.buono (Can’t mention). The difference between your code block and mine is that yours use spaces and mine uses tabs for indentation. Mine with tab size 4 still gives me warnings, while yours using spaces do not. Unfortunately, my project uses tabs for indentation in all classes, so using spaces now would not be feasible.

Is it a configuration that I can change that would recognize the tabs indentation being correct?

1 Like

Hello @marinello,

The rule implementation seems to be correct: it checks that the column offset of the first character on an indented line is the expected multiple of the indentation level set, if this condition is not true then an issue is raised.

After some research the issue may depend on the different defaults for the tab character per OS (see Do IDEs and compilers have different spacing for /t spacing? (JAVA on IntelliJ) and Tabs “can be displayed completely differently on different types of systems and editors”?). The recommendation is to configure the IDE to use spaces for indentation. Try to configure VS Code to use spaces for indentation when pressing the tab.

Cheers,
Angelo

I tried using tabs with width from 1 to 8, and the issue still occurs. I can’t change my white space usage as tabs are the default for this project (And the usage of spaces vs tabs were already discussed in various other topics on the internet, both having their advantages).

As the project uses tabs as default and I can’t change it, and the issue still occurs using any tab width (Well, from 1 to 8, but who’s gonna want to use more than 8?), I still think that the rule is incorrect, as it raises with a perfectly indented code.

It may raise even in lambda functions when using ternary operators:

public class Test {
	public static void main(String[] args) {
		var toLambda = List.of(1, 2, 3, 4, 5);

		var mapped = toLambda.stream().map((Integer x) -> {
			double toReturn = x > 10 ? 0D : 1D;
			toReturn = toReturn + 1;

			return toReturn;
		});

		mapped.forEach(System.out::println);
	}
}

With spaces, it doesn’t raise the rule, so indeed something fishy is going on with the tabs indentation.

Another point of problem is with the new switches in Java 13 switch Expressions, that also break in the same manner as the other examples when using tabs for indentation instead of spaces.

Hello :wave: as far as I can tell, changing the displayed width of tabs in the IDE won’t have any effect over the behavior of the analysis: a tab character is considered as a single indentation level, regardless of how it is displayed.

If your choice is to stick with tabs for indentation (I won’t judge I promise :stuck_out_tongue_winking_eye:), you can configure the indentationLevel parameter of rule java:S1120.

There is currently no graphical UI provided by SonarLint to do so, however you should be able to set this in your user settings JSON:

{
    "sonarlint.rules": {
        "java:S1120": {
            "level": "on",
            "parameters": {
                "indentationLevel": 1
            }
        }
    }
}

With this setting, I believe that the behavior is consistent - see screenshot below.

2 Likes