3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.api.batch.sensor.symbol.internal;
22 import java.util.Collection;
23 import java.util.LinkedHashMap;
26 import java.util.TreeSet;
27 import org.sonar.api.batch.fs.InputFile;
28 import org.sonar.api.batch.fs.TextRange;
29 import org.sonar.api.batch.fs.internal.DefaultInputFile;
30 import org.sonar.api.batch.sensor.internal.DefaultStorable;
31 import org.sonar.api.batch.sensor.internal.SensorStorage;
32 import org.sonar.api.batch.sensor.symbol.NewSymbol;
33 import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
35 import static java.util.Objects.requireNonNull;
36 import static org.sonar.api.utils.Preconditions.checkArgument;
37 import static org.sonar.api.utils.Preconditions.checkState;
39 public class DefaultSymbolTable extends DefaultStorable implements NewSymbolTable {
41 private final Map<TextRange, Set<TextRange>> referencesBySymbol;
42 private DefaultInputFile inputFile;
44 public DefaultSymbolTable(SensorStorage storage) {
46 referencesBySymbol = new LinkedHashMap<>();
49 public Map<TextRange, Set<TextRange>> getReferencesBySymbol() {
50 return referencesBySymbol;
54 public DefaultSymbolTable onFile(InputFile inputFile) {
55 requireNonNull(inputFile, "file can't be null");
56 this.inputFile = (DefaultInputFile) inputFile;
60 public InputFile inputFile() {
65 public NewSymbol newSymbol(int startLine, int startLineOffset, int endLine, int endLineOffset) {
66 checkInputFileNotNull();
67 TextRange declarationRange;
69 declarationRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
70 } catch (Exception e) {
71 throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
73 return newSymbol(declarationRange);
77 public NewSymbol newSymbol(TextRange range) {
78 checkInputFileNotNull();
79 TreeSet<TextRange> references = new TreeSet<>((o1, o2) -> o1.start().compareTo(o2.start()));
80 referencesBySymbol.put(range, references);
81 return new DefaultSymbol(inputFile, range, references);
84 private static class DefaultSymbol implements NewSymbol {
86 private final Collection<TextRange> references;
87 private final DefaultInputFile inputFile;
88 private final TextRange declaration;
90 public DefaultSymbol(DefaultInputFile inputFile, TextRange declaration, Collection<TextRange> references) {
91 this.inputFile = inputFile;
92 this.declaration = declaration;
93 this.references = references;
97 public NewSymbol newReference(int startLine, int startLineOffset, int endLine, int endLineOffset) {
98 TextRange referenceRange;
100 referenceRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
101 } catch (Exception e) {
102 throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
104 return newReference(referenceRange);
108 public NewSymbol newReference(TextRange range) {
109 requireNonNull(range, "Provided range is null");
110 checkArgument(!declaration.overlap(range), "Overlapping symbol declaration and reference for symbol at %s", declaration);
111 references.add(range);
118 protected void doSave() {
119 checkInputFileNotNull();
123 private void checkInputFileNotNull() {
124 checkState(inputFile != null, "Call onFile() first");