]> source.dussan.org Git - sonarqube.git/blob
4db7a419b02c0c34b7486a02681250769ff668eb
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2023 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.api.batch.sensor.symbol.internal;
21
22 import java.util.Collection;
23 import java.util.LinkedHashMap;
24 import java.util.Map;
25 import java.util.Set;
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;
34
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;
38
39 public class DefaultSymbolTable extends DefaultStorable implements NewSymbolTable {
40
41   private final Map<TextRange, Set<TextRange>> referencesBySymbol;
42   private DefaultInputFile inputFile;
43
44   public DefaultSymbolTable(SensorStorage storage) {
45     super(storage);
46     referencesBySymbol = new LinkedHashMap<>();
47   }
48
49   public Map<TextRange, Set<TextRange>> getReferencesBySymbol() {
50     return referencesBySymbol;
51   }
52
53   @Override
54   public DefaultSymbolTable onFile(InputFile inputFile) {
55     requireNonNull(inputFile, "file can't be null");
56     this.inputFile = (DefaultInputFile) inputFile;
57     return this;
58   }
59
60   public InputFile inputFile() {
61     return inputFile;
62   }
63
64   @Override
65   public NewSymbol newSymbol(int startLine, int startLineOffset, int endLine, int endLineOffset) {
66     checkInputFileNotNull();
67     TextRange declarationRange;
68     try {
69       declarationRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
70     } catch (Exception e) {
71       throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
72     }
73     return newSymbol(declarationRange);
74   }
75
76   @Override
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);
82   }
83
84   private static class DefaultSymbol implements NewSymbol {
85
86     private final Collection<TextRange> references;
87     private final DefaultInputFile inputFile;
88     private final TextRange declaration;
89
90     public DefaultSymbol(DefaultInputFile inputFile, TextRange declaration, Collection<TextRange> references) {
91       this.inputFile = inputFile;
92       this.declaration = declaration;
93       this.references = references;
94     }
95
96     @Override
97     public NewSymbol newReference(int startLine, int startLineOffset, int endLine, int endLineOffset) {
98       TextRange referenceRange;
99       try {
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);
103       }
104       return newReference(referenceRange);
105     }
106
107     @Override
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);
112       return this;
113     }
114
115   }
116
117   @Override
118   protected void doSave() {
119     checkInputFileNotNull();
120     storage.store(this);
121   }
122
123   private void checkInputFileNotNull() {
124     checkState(inputFile != null, "Call onFile() first");
125   }
126 }